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

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

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