Annotation of embedaddon/quagga/isisd/isis_dlpi.c, revision 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>