Annotation of embedaddon/quagga/isisd/isis_dlpi.c, revision 1.1.1.1

1.1       misho       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>