File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / isisd / isis_dlpi.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:26:11 2012 UTC (12 years, 4 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_20_1, v0_99_20, HEAD
quagga

    1: /*
    2:  * IS-IS Rout(e)ing protocol - isis_dlpi.c
    3:  *
    4:  * Copyright (C) 2001,2002    Sampo Saaristo
    5:  *                            Tampere University of Technology      
    6:  *                            Institute of Communications Engineering
    7:  *
    8:  * This program is free software; you can redistribute it and/or modify it 
    9:  * under the terms of the GNU General Public Licenseas published by the Free 
   10:  * Software Foundation; either version 2 of the License, or (at your option) 
   11:  * any later version.
   12:  *
   13:  * This program is distributed in the hope that it will be useful,but WITHOUT 
   14:  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
   15:  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
   16:  * more details.
   17: 
   18:  * You should have received a copy of the GNU General Public License along 
   19:  * with this program; if not, write to the Free Software Foundation, Inc., 
   20:  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   21:  */
   22: 
   23: #include <zebra.h>
   24: #if ISIS_METHOD == ISIS_METHOD_DLPI
   25: #include <net/if.h>
   26: #include <netinet/if_ether.h>
   27: #include <sys/types.h>
   28: #include <unistd.h>
   29: #include <fcntl.h>
   30: #include <stropts.h>
   31: #include <poll.h>
   32: #include <sys/dlpi.h>
   33: #include <sys/pfmod.h>
   34: 
   35: #include "log.h"
   36: #include "stream.h"
   37: #include "if.h"
   38: 
   39: #include "isisd/dict.h"
   40: #include "isisd/include-netbsd/iso.h"
   41: #include "isisd/isis_constants.h"
   42: #include "isisd/isis_common.h"
   43: #include "isisd/isis_circuit.h"
   44: #include "isisd/isis_flags.h"
   45: #include "isisd/isisd.h"
   46: #include "isisd/isis_network.h"
   47: 
   48: #include "privs.h"
   49: 
   50: extern struct zebra_privs_t isisd_privs;
   51: 
   52: static t_uscalar_t dlpi_ctl[1024];	/* DLPI control messages */
   53: 
   54: /*
   55:  * Table 9 - Architectural constants for use with ISO 8802 subnetworks
   56:  * ISO 10589 - 8.4.8
   57:  */
   58: 
   59: u_char ALL_L1_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x14 };
   60: u_char ALL_L2_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x15 };
   61: u_char ALL_ISS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x05 };
   62: u_char ALL_ESS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x04 };
   63: 
   64: static u_char sock_buff[8192];
   65: 
   66: static u_short pf_filter[] =
   67: {
   68:   ENF_PUSHWORD + 0,		/* Get the SSAP/DSAP values */
   69:   ENF_PUSHLIT | ENF_CAND,	/* Check them */
   70:   ISO_SAP | (ISO_SAP << 8),
   71:   ENF_PUSHWORD + 1,		/* Get the control value */
   72:   ENF_PUSHLIT | ENF_AND,	/* Isolate it */
   73: #ifdef _BIG_ENDIAN
   74:   0xFF00,
   75: #else
   76:   0x00FF,
   77: #endif
   78:   ENF_PUSHLIT | ENF_CAND,	/* Test for expected value */
   79: #ifdef _BIG_ENDIAN
   80:   0x0300
   81: #else
   82:   0x0003
   83: #endif
   84: };
   85: 
   86: /*
   87:  * We would like to use something like libdlpi here, but that's not present on
   88:  * all versions of Solaris or on any non-Solaris system, so it's nowhere near
   89:  * as portable as we'd like.  Thus, we use the standards-conformant DLPI
   90:  * interfaces plus the (optional; not needed) Solaris packet filter module.
   91:  */
   92: 
   93: static void
   94: dlpisend (int fd, const void *cbuf, size_t cbuflen,
   95:   const void *dbuf, size_t dbuflen, int flags)
   96: {
   97:   const struct strbuf *ctlptr = NULL;
   98:   const struct strbuf *dataptr = NULL;
   99:   struct strbuf ctlbuf, databuf;
  100: 
  101:   if (cbuf != NULL)
  102:     {
  103:       memset (&ctlbuf, 0, sizeof (ctlbuf));
  104:       ctlbuf.len = cbuflen;
  105:       ctlbuf.buf = (void *)cbuf;
  106:       ctlptr = &ctlbuf;
  107:     }
  108: 
  109:   if (dbuf != NULL)
  110:     {
  111:       memset (&databuf, 0, sizeof (databuf));
  112:       databuf.len = dbuflen;
  113:       databuf.buf = (void *)dbuf;
  114:       dataptr = &databuf;
  115:     }
  116: 
  117:   /* We assume this doesn't happen often and isn't operationally significant */
  118:   if (putmsg (fd, ctlptr, dataptr, flags) == -1)
  119:     zlog_debug ("%s: putmsg: %s", __func__, safe_strerror (errno));
  120: }
  121: 
  122: static ssize_t
  123: dlpirctl (int fd)
  124: {
  125:   struct pollfd fds[1];
  126:   struct strbuf ctlbuf, databuf;
  127:   int flags, retv;
  128: 
  129:   do
  130:     {
  131:       /* Poll is used here in case the device doesn't speak DLPI correctly */
  132:       memset (fds, 0, sizeof (fds));
  133:       fds[0].fd = fd;
  134:       fds[0].events = POLLIN | POLLPRI;
  135:       if (poll (fds, 1, 1000) <= 0)
  136: 	return -1;
  137: 
  138:       memset (&ctlbuf, 0, sizeof (ctlbuf));
  139:       memset (&databuf, 0, sizeof (databuf));
  140:       ctlbuf.maxlen = sizeof (dlpi_ctl);
  141:       ctlbuf.buf = (void *)dlpi_ctl;
  142:       databuf.maxlen = sizeof (sock_buff);
  143:       databuf.buf = (void *)sock_buff;
  144:       flags = 0;
  145:       retv = getmsg (fd, &ctlbuf, &databuf, &flags);
  146: 
  147:       if (retv < 0)
  148: 	return -1;
  149:     }
  150:   while (ctlbuf.len == 0);
  151: 
  152:   if (!(retv & MORECTL))
  153:     {
  154:       while (retv & MOREDATA)
  155: 	{
  156: 	  flags = 0;
  157: 	  retv = getmsg (fd, NULL, &databuf, &flags);
  158: 	}
  159:       return ctlbuf.len;
  160:     }
  161: 
  162:   while (retv & MORECTL)
  163:     {
  164:       flags = 0;
  165:       retv = getmsg (fd, &ctlbuf, &databuf, &flags);
  166:     }
  167:   return -1;
  168: }
  169: 
  170: static int
  171: dlpiok (int fd, t_uscalar_t oprim)
  172: {
  173:   int retv;
  174:   dl_ok_ack_t *doa = (dl_ok_ack_t *)dlpi_ctl;
  175: 
  176:   retv = dlpirctl (fd);
  177:   if (retv < DL_OK_ACK_SIZE || doa->dl_primitive != DL_OK_ACK ||
  178:     doa->dl_correct_primitive != oprim)
  179:     {
  180:       return -1;
  181:     }
  182:   else
  183:     {
  184:       return 0;
  185:     }
  186: }
  187: 
  188: static int
  189: dlpiinfo (int fd)
  190: {
  191:   dl_info_req_t dir;
  192:   ssize_t retv;
  193: 
  194:   memset (&dir, 0, sizeof (dir));
  195:   dir.dl_primitive = DL_INFO_REQ;
  196:   /* Info_req uses M_PCPROTO. */
  197:   dlpisend (fd, &dir, sizeof (dir), NULL, 0, RS_HIPRI);
  198:   retv = dlpirctl (fd);
  199:   if (retv < DL_INFO_ACK_SIZE || dlpi_ctl[0] != DL_INFO_ACK)
  200:     return -1;
  201:   else
  202:     return retv;
  203: }
  204: 
  205: static int
  206: dlpiopen (const char *devpath, ssize_t *acklen)
  207: {
  208:   int fd, flags;
  209: 
  210:   fd = open (devpath, O_RDWR | O_NONBLOCK | O_NOCTTY);
  211:   if (fd == -1)
  212:     return -1;
  213: 
  214:   /* All that we want is for the open itself to be non-blocking, not I/O. */
  215:   flags = fcntl (fd, F_GETFL, 0);
  216:   if (flags != -1)
  217:     fcntl (fd, F_SETFL, flags & ~O_NONBLOCK);
  218: 
  219:   /* After opening, ask for information */
  220:   if ((*acklen = dlpiinfo (fd)) == -1)
  221:     {
  222:       close (fd);
  223:       return -1;
  224:     }
  225: 
  226:   return fd;
  227: }
  228: 
  229: static int
  230: dlpiattach (int fd, int unit)
  231: {
  232:   dl_attach_req_t dar;
  233: 
  234:   memset (&dar, 0, sizeof (dar));
  235:   dar.dl_primitive = DL_ATTACH_REQ;
  236:   dar.dl_ppa = unit;
  237:   dlpisend (fd, &dar, sizeof (dar), NULL, 0, 0);
  238:   return dlpiok (fd, dar.dl_primitive);
  239: }
  240: 
  241: static int
  242: dlpibind (int fd)
  243: {
  244:   dl_bind_req_t dbr;
  245:   int retv;
  246:   dl_bind_ack_t *dba = (dl_bind_ack_t *)dlpi_ctl;
  247: 
  248:   memset (&dbr, 0, sizeof (dbr));
  249:   dbr.dl_primitive = DL_BIND_REQ;
  250:   dbr.dl_service_mode = DL_CLDLS;
  251:   dlpisend (fd, &dbr, sizeof (dbr), NULL, 0, 0);
  252: 
  253:   retv = dlpirctl (fd);
  254:   if (retv < DL_BIND_ACK_SIZE || dba->dl_primitive != DL_BIND_ACK)
  255:     return -1;
  256:   else
  257:     return 0;
  258: }
  259: 
  260: static int
  261: dlpimcast (int fd, const u_char *mcaddr)
  262: {
  263:   struct {
  264:     dl_enabmulti_req_t der;
  265:     u_char addr[ETHERADDRL];
  266:   } dler;
  267: 
  268:   memset (&dler, 0, sizeof (dler));
  269:   dler.der.dl_primitive = DL_ENABMULTI_REQ;
  270:   dler.der.dl_addr_length = sizeof (dler.addr);
  271:   dler.der.dl_addr_offset = dler.addr - (u_char *)&dler;
  272:   memcpy (dler.addr, mcaddr, sizeof (dler.addr));
  273:   dlpisend (fd, &dler, sizeof (dler), NULL, 0, 0);
  274:   return dlpiok (fd, dler.der.dl_primitive);
  275: }
  276: 
  277: static int
  278: dlpiaddr (int fd, u_char *addr)
  279: {
  280:   dl_phys_addr_req_t dpar;
  281:   dl_phys_addr_ack_t *dpaa = (dl_phys_addr_ack_t *)dlpi_ctl;
  282:   int retv;
  283: 
  284:   memset (&dpar, 0, sizeof (dpar));
  285:   dpar.dl_primitive = DL_PHYS_ADDR_REQ;
  286:   dpar.dl_addr_type = DL_CURR_PHYS_ADDR;
  287:   dlpisend (fd, &dpar, sizeof (dpar), NULL, 0, 0);
  288: 
  289:   retv = dlpirctl (fd);
  290:   if (retv < DL_PHYS_ADDR_ACK_SIZE || dpaa->dl_primitive != DL_PHYS_ADDR_ACK)
  291:     return -1;
  292: 
  293:   if (dpaa->dl_addr_offset < DL_PHYS_ADDR_ACK_SIZE ||
  294:     dpaa->dl_addr_length != ETHERADDRL ||
  295:     dpaa->dl_addr_offset + dpaa->dl_addr_length > retv)
  296:     return -1;
  297: 
  298:   bcopy((char *)dpaa + dpaa->dl_addr_offset, addr, ETHERADDRL);
  299:   return 0;
  300: }
  301: 
  302: static int
  303: open_dlpi_dev (struct isis_circuit *circuit)
  304: {
  305:   int fd, unit, retval;
  306:   char devpath[MAXPATHLEN];
  307:   dl_info_ack_t *dia = (dl_info_ack_t *)dlpi_ctl;
  308:   ssize_t acklen;
  309: 
  310:   /* Only broadcast-type are supported at the moment */
  311:   if (circuit->circ_type != CIRCUIT_T_BROADCAST)
  312:     {
  313:       zlog_warn ("%s: non-broadcast interface %s", __func__,
  314: 	circuit->interface->name);
  315:       return ISIS_WARNING;
  316:     }
  317:   
  318:   /* Try the vanity node first, if permitted */
  319:   if (getenv("DLPI_DEVONLY") == NULL)
  320:     {
  321:       (void) snprintf (devpath, sizeof(devpath), "/dev/net/%s",
  322:                       circuit->interface->name);
  323:       fd = dlpiopen (devpath, &acklen);
  324:     }
  325:   
  326:   /* Now try as an ordinary Style 1 node */
  327:   if (fd == -1)
  328:     {
  329:       (void) snprintf (devpath, sizeof (devpath), "/dev/%s",
  330:                       circuit->interface->name);
  331:       unit = -1;
  332:       fd = dlpiopen (devpath, &acklen);
  333:     }
  334: 
  335:   /* If that fails, try again as Style 2 */
  336:   if (fd == -1)
  337:     {
  338:       char *cp;
  339: 
  340:       cp = devpath + strlen (devpath);
  341:       while (--cp >= devpath && isdigit(*cp))
  342: 	;
  343:       unit = strtol(cp, NULL, 0);
  344:       *cp = '\0';
  345:       fd = dlpiopen (devpath, &acklen);
  346: 
  347:       /* If that too fails, then the device really doesn't exist */
  348:       if (fd == -1)
  349: 	{
  350: 	  zlog_warn ("%s: unknown interface %s", __func__,
  351: 	    circuit->interface->name);
  352: 	  return ISIS_WARNING;
  353: 	}
  354: 
  355:       /* Double check the DLPI style */
  356:       if (dia->dl_provider_style != DL_STYLE2)
  357: 	{
  358: 	  zlog_warn ("open_dlpi_dev(): interface %s: %s is not style 2",
  359: 	    circuit->interface->name, devpath);
  360: 	  close (fd);
  361: 	  return ISIS_WARNING;
  362: 	}
  363: 
  364:       /* If it succeeds, then we need to attach to the unit specified */
  365:       dlpiattach (fd, unit);
  366: 
  367:       /* Reget the information, as it may be different per node */
  368:       if ((acklen = dlpiinfo (fd)) == -1)
  369: 	{
  370: 	  close (fd);
  371: 	  return ISIS_WARNING;
  372: 	}
  373:     }
  374:   else
  375:     {
  376:       /* Double check the DLPI style */
  377:       if (dia->dl_provider_style != DL_STYLE1)
  378: 	{
  379: 	  zlog_warn ("open_dlpi_dev(): interface %s: %s is not style 1",
  380: 	    circuit->interface->name, devpath);
  381: 	  close (fd);
  382: 	  return ISIS_WARNING;
  383: 	}
  384:     }
  385: 
  386:   /* Check that the interface we've got is the kind we expect */
  387:   if ((dia->dl_sap_length != 2 && dia->dl_sap_length != -2) ||
  388:     dia->dl_service_mode != DL_CLDLS || dia->dl_addr_length != ETHERADDRL + 2 ||
  389:     dia->dl_brdcst_addr_length != ETHERADDRL)
  390:     {
  391:       zlog_warn ("%s: unsupported interface type for %s", __func__,
  392: 	circuit->interface->name);
  393:       close (fd);
  394:       return ISIS_WARNING;
  395:     }
  396:   switch (dia->dl_mac_type)
  397:     {
  398:     case DL_CSMACD:
  399:     case DL_ETHER:
  400:     case DL_100VG:
  401:     case DL_100VGTPR:
  402:     case DL_ETH_CSMA:
  403:     case DL_100BT:
  404:       break;
  405:     default:
  406:       zlog_warn ("%s: unexpected mac type on %s: %d", __func__,
  407: 	circuit->interface->name, dia->dl_mac_type);
  408:       close (fd);
  409:       return ISIS_WARNING;
  410:     }
  411: 
  412:   circuit->sap_length = dia->dl_sap_length;
  413: 
  414:   /*
  415:    * The local hardware address is something that should be provided by way of
  416:    * sockaddr_dl for the interface, but isn't on Solaris.  We set it here based
  417:    * on DLPI's reported address to avoid roto-tilling the world.
  418:    * (Note that isis_circuit_if_add on Solaris doesn't set the snpa.)
  419:    *
  420:    * Unfortunately, GLD is broken and doesn't provide the address after attach,
  421:    * so we need to be careful and use DL_PHYS_ADDR_REQ instead.
  422:    */
  423:   if (dlpiaddr (fd, circuit->u.bc.snpa) == -1)
  424:     {
  425:       zlog_warn ("open_dlpi_dev(): interface %s: unable to get MAC address",
  426: 	circuit->interface->name);
  427:       close (fd);
  428:       return ISIS_WARNING;
  429:     }
  430: 
  431:   /* Now bind to SAP 0.  This gives us 802-type traffic. */
  432:   if (dlpibind (fd) == -1)
  433:     {
  434:       zlog_warn ("%s: cannot bind SAP 0 on %s", __func__,
  435: 	circuit->interface->name);
  436:       close (fd);
  437:       return ISIS_WARNING;
  438:     }
  439: 
  440:   /*
  441:    * Join to multicast groups according to
  442:    * 8.4.2 - Broadcast subnetwork IIH PDUs
  443:    */
  444:   retval = 0;
  445:   if (circuit->circuit_is_type & IS_LEVEL_1)
  446:     {
  447:       retval |= dlpimcast (fd, ALL_L1_ISS);
  448:       retval |= dlpimcast (fd, ALL_ISS);
  449:     }
  450:   if (circuit->circuit_is_type & IS_LEVEL_2)
  451:     retval |= dlpimcast (fd, ALL_L2_ISS);
  452: 
  453:   if (retval != 0)
  454:     {
  455:       zlog_warn ("%s: unable to join multicast on %s", __func__,
  456: 	circuit->interface->name);
  457:       close (fd);
  458:       return ISIS_WARNING;
  459:     }
  460: 
  461:   /* Push on the packet filter to avoid stray 802 packets */
  462:   if (ioctl (fd, I_PUSH, "pfmod") == 0)
  463:     {
  464:       struct packetfilt pfil;
  465:       struct strioctl sioc;
  466: 
  467:       pfil.Pf_Priority = 0;
  468:       pfil.Pf_FilterLen = sizeof (pf_filter) / sizeof (u_short);
  469:       memcpy (pfil.Pf_Filter, pf_filter, sizeof (pf_filter));
  470:       /* pfmod does not support transparent ioctls */
  471:       sioc.ic_cmd = PFIOCSETF;
  472:       sioc.ic_timout = 5;
  473:       sioc.ic_len = sizeof (struct packetfilt);
  474:       sioc.ic_dp = (char *)&pfil;
  475:       if (ioctl (fd, I_STR, &sioc) == -1)
  476:          zlog_warn("%s: could not perform PF_IOCSETF on %s",
  477:            __func__, circuit->interface->name); 
  478:     }
  479: 
  480:   circuit->fd = fd;
  481: 
  482:   return ISIS_OK;
  483: }
  484: 
  485: /*
  486:  * Create the socket and set the tx/rx funcs
  487:  */
  488: int
  489: isis_sock_init (struct isis_circuit *circuit)
  490: {
  491:   int retval = ISIS_OK;
  492: 
  493:   if (isisd_privs.change (ZPRIVS_RAISE))
  494:     zlog_err ("%s: could not raise privs, %s", __func__, safe_strerror (errno));
  495: 
  496:   retval = open_dlpi_dev (circuit);
  497: 
  498:   if (retval != ISIS_OK)
  499:     {
  500:       zlog_warn ("%s: could not initialize the socket", __func__);
  501:       goto end;
  502:     }
  503: 
  504:   if (circuit->circ_type == CIRCUIT_T_BROADCAST)
  505:     {
  506:       circuit->tx = isis_send_pdu_bcast;
  507:       circuit->rx = isis_recv_pdu_bcast;
  508:     }
  509:   else
  510:     {
  511:       zlog_warn ("isis_sock_init(): unknown circuit type");
  512:       retval = ISIS_WARNING;
  513:       goto end;
  514:     }
  515: 
  516: end:
  517:   if (isisd_privs.change (ZPRIVS_LOWER))
  518:     zlog_err ("%s: could not lower privs, %s", __func__, safe_strerror (errno));
  519: 
  520:   return retval;
  521: }
  522: 
  523: int
  524: isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa)
  525: {
  526:   struct pollfd fds[1];
  527:   struct strbuf ctlbuf, databuf;
  528:   int flags, retv;
  529:   dl_unitdata_ind_t *dui = (dl_unitdata_ind_t *)dlpi_ctl;
  530: 
  531:   memset (fds, 0, sizeof (fds));
  532:   fds[0].fd = circuit->fd;
  533:   fds[0].events = POLLIN | POLLPRI;
  534:   if (poll (fds, 1, 0) <= 0)
  535:     return ISIS_WARNING;
  536: 
  537:   memset (&ctlbuf, 0, sizeof (ctlbuf));
  538:   memset (&databuf, 0, sizeof (databuf));
  539:   ctlbuf.maxlen = sizeof (dlpi_ctl);
  540:   ctlbuf.buf = (void *)dlpi_ctl;
  541:   databuf.maxlen = sizeof (sock_buff);
  542:   databuf.buf = (void *)sock_buff;
  543:   flags = 0;
  544:   retv = getmsg (circuit->fd, &ctlbuf, &databuf, &flags);
  545: 
  546:   if (retv < 0)
  547:     {
  548:       zlog_warn ("isis_recv_pdu_bcast: getmsg failed: %s",
  549: 		 safe_strerror (errno));
  550:       return ISIS_WARNING;
  551:     }
  552: 
  553:   if (retv & (MORECTL | MOREDATA))
  554:     {
  555:       while (retv & (MORECTL | MOREDATA))
  556: 	{
  557: 	  flags = 0;
  558: 	  retv = getmsg (circuit->fd, &ctlbuf, &databuf, &flags);
  559: 	}
  560:       return ISIS_WARNING;
  561:     }
  562: 
  563:   if (ctlbuf.len < DL_UNITDATA_IND_SIZE ||
  564:     dui->dl_primitive != DL_UNITDATA_IND)
  565:     return ISIS_WARNING;
  566: 
  567:   if (dui->dl_src_addr_length != ETHERADDRL + 2 ||
  568:     dui->dl_src_addr_offset < DL_UNITDATA_IND_SIZE ||
  569:     dui->dl_src_addr_offset + dui->dl_src_addr_length > ctlbuf.len)
  570:     return ISIS_WARNING;
  571: 
  572:   memcpy (ssnpa, (char *)dui + dui->dl_src_addr_offset +
  573:     (circuit->sap_length > 0 ? circuit->sap_length : 0), ETHERADDRL);
  574: 
  575:   if (databuf.len < LLC_LEN || sock_buff[0] != ISO_SAP ||
  576:     sock_buff[1] != ISO_SAP || sock_buff[2] != 3)
  577:     return ISIS_WARNING;
  578: 
  579:   stream_write (circuit->rcv_stream, sock_buff + LLC_LEN,
  580:                 databuf.len - LLC_LEN);
  581:   stream_set_getp (circuit->rcv_stream, 0);
  582: 
  583:   return ISIS_OK;
  584: }
  585: 
  586: int
  587: isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
  588: {
  589:   dl_unitdata_req_t *dur = (dl_unitdata_req_t *)dlpi_ctl;
  590:   char *dstaddr;
  591:   u_short *dstsap;
  592: 
  593:   stream_set_getp (circuit->snd_stream, 0);
  594: 
  595:   memset (dur, 0, sizeof (*dur));
  596:   dur->dl_primitive = DL_UNITDATA_REQ;
  597:   dur->dl_dest_addr_length = ETHERADDRL + 2;
  598:   dur->dl_dest_addr_offset = sizeof (*dur);
  599: 
  600:   dstaddr = (char *)(dur + 1);
  601:   if (circuit->sap_length < 0)
  602:     {
  603:       dstsap = (u_short *)(dstaddr + ETHERADDRL);
  604:     }
  605:   else
  606:     {
  607:       dstsap = (u_short *)dstaddr;
  608:       dstaddr += circuit->sap_length;
  609:     }
  610:   if (level == 1)
  611:     memcpy (dstaddr, ALL_L1_ISS, ETHERADDRL);
  612:   else
  613:     memcpy (dstaddr, ALL_L2_ISS, ETHERADDRL);
  614:   /* Note: DLPI SAP values are in host byte order */
  615:   *dstsap = stream_get_endp (circuit->snd_stream) + LLC_LEN;
  616: 
  617:   sock_buff[0] = ISO_SAP;
  618:   sock_buff[1] = ISO_SAP;
  619:   sock_buff[2] = 0x03;
  620:   memcpy (sock_buff + LLC_LEN, circuit->snd_stream->data,
  621: 	  stream_get_endp (circuit->snd_stream));
  622:   dlpisend (circuit->fd, dur, sizeof (*dur) + dur->dl_dest_addr_length,
  623:     sock_buff, stream_get_endp (circuit->snd_stream) + LLC_LEN, 0);
  624:   return ISIS_OK;
  625: }
  626: 
  627: #endif /* ISIS_METHOD == ISIS_METHOD_DLPI */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>