Annotation of embedaddon/dhcp/common/dlpi.c, revision 1.1.1.1

1.1       misho       1: /* dlpi.c
                      2:  
                      3:    Data Link Provider Interface (DLPI) network interface code. */
                      4: 
                      5: /*
                      6:  * Copyright (c) 2009-2011 by Internet Systems Consortium, Inc. ("ISC")
                      7:  * Copyright (c) 2004,2007 by Internet Systems Consortium, Inc. ("ISC")
                      8:  * Copyright (c) 1996-2003 by Internet Software Consortium
                      9:  *
                     10:  * Permission to use, copy, modify, and distribute this software for any
                     11:  * purpose with or without fee is hereby granted, provided that the above
                     12:  * copyright notice and this permission notice appear in all copies.
                     13:  *
                     14:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
                     15:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     16:  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
                     17:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     18:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     19:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
                     20:  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     21:  *
                     22:  *   Internet Systems Consortium, Inc.
                     23:  *   950 Charter Street
                     24:  *   Redwood City, CA 94063
                     25:  *   <info@isc.org>
                     26:  *   https://www.isc.org/
                     27:  *
                     28:  * This software was written for Internet Systems Consortium
                     29:  * by Eric James Negaard, <lmdejn@lmd.ericsson.se>.  To learn more about
                     30:  * Internet Systems Consortium, see ``https://www.isc.org''.
                     31:  *
                     32:  * Joost Mulders has also done considerable work in debugging the DLPI API
                     33:  * support on Solaris and getting this code to work properly on a variety
                     34:  * of different Solaris platforms.
                     35:  */
                     36: 
                     37: /*
                     38:  * Based largely in part to the existing NIT code in nit.c.
                     39:  *
                     40:  * This code has been developed and tested on sparc-based machines running
                     41:  * SunOS 5.5.1, with le and hme network interfaces.  It should be pretty
                     42:  * generic, though.
                     43:  */
                     44: 
                     45: /*
                     46:  * Implementation notes:
                     47:  *
                     48:  * I first tried to write this code to the "vanilla" DLPI 2.0 API.
                     49:  * It worked on a Sun Ultra-1 with a hme interface, but didn't work
                     50:  * on Sun SparcStation 5's with "le" interfaces (the packets sent out
                     51:  * via dlpiunitdatareq contained an Ethernet type of 0x0000 instead
                     52:  * of the expected 0x0800).
                     53:  *
                     54:  * Therefore I added the "DLPI_RAW" code which is a Sun extension to
                     55:  * the DLPI standard.  This code works on both of the above machines.
                     56:  * This is configurable in the OS-dependent include file by defining
                     57:  * USE_DLPI_RAW.
                     58:  *
                     59:  * It quickly became apparant that I should also use the "pfmod"
                     60:  * STREAMS module to cut down on the amount of user level packet
                     61:  * processing.  I don't know how widely available "pfmod" is, so it's
                     62:  * use is conditionally included. This is configurable in the
                     63:  * OS-dependent include file by defining USE_DLPI_PFMOD.
                     64:  *
                     65:  * A major quirk on the Sun's at least, is that no packets seem to get
                     66:  * sent out the interface until six seconds after the interface is
                     67:  * first "attached" to [per system reboot] (it's actually from when
                     68:  * the interface is attached, not when it is plumbed, so putting a
                     69:  * sleep into the dhclient-script at PREINIT time doesn't help).  I
                     70:  * HAVE tried, without success to poll the fd to see when it is ready
                     71:  * for writing.  This doesn't help at all. If the sleeps are not done,
                     72:  * the initial DHCPREQUEST or DHCPDISCOVER never gets sent out, so
                     73:  * I've put them here, when register_send and register_receive are
                     74:  * called (split up into two three-second sleeps between the notices,
                     75:  * so that it doesn't seem like so long when you're watching :-).  The
                     76:  * amount of time to sleep is configurable in the OS-dependent include
                     77:  * file by defining DLPI_FIRST_SEND_WAIT to be the number of seconds
                     78:  * to sleep.
                     79:  */
                     80: 
                     81: /*
                     82:  * The Open Group Technical Standard can be found here:
                     83:  * http://www.opengroup.org/onlinepubs/009618899/index.htm
                     84:  *
                     85:  * The HP DLPI Programmer's Guide can be found here:
                     86:  * http://docs.hp.com/en/B2355-90139/index.html
                     87:  */
                     88: 
                     89: #include "dhcpd.h"
                     90: 
                     91: #if defined (USE_DLPI_SEND) || defined (USE_DLPI_RECEIVE) || \
                     92:     defined(USE_DLPI_HWADDR)
                     93: 
                     94: # include <sys/ioctl.h>
                     95: # include <sys/time.h>
                     96: # include <sys/dlpi.h>
                     97: # include <stropts.h>
                     98: # ifdef USE_DLPI_PFMOD
                     99: #  include <sys/pfmod.h>
                    100: # endif
                    101: #include <poll.h>
                    102: #include <errno.h>
                    103: 
                    104: # include <netinet/in_systm.h>
                    105: # include "includes/netinet/ip.h"
                    106: # include "includes/netinet/udp.h"
                    107: # include "includes/netinet/if_ether.h"
                    108: 
                    109: # ifdef USE_DLPI_PFMOD
                    110: #  ifdef USE_DLPI_RAW
                    111: #   define DLPI_MODNAME "DLPI+RAW+PFMOD"
                    112: #  else
                    113: #   define DLPI_MODNAME "DLPI+PFMOD"
                    114: #  endif
                    115: # else
                    116: #  ifdef USE_DLPI_RAW
                    117: #   define DLPI_MODNAME "DLPI+RAW"
                    118: #  else
                    119: #   define DLPI_MODNAME "DLPI"
                    120: #  endif
                    121: # endif
                    122: 
                    123: # ifndef ABS
                    124: #  define ABS(x) ((x) >= 0 ? (x) : 0-(x))
                    125: # endif
                    126: 
                    127: #if defined(USE_DLPI_PFMOD) || defined(USE_DLPI_RAW)
                    128: static int strioctl (int fd, int cmd, int timeout, int len, char *dp);
                    129: #endif
                    130: 
                    131: #define DLPI_MAXDLBUF          8192    /* Buffer size */
                    132: #define DLPI_MAXDLADDR         1024    /* Max address size */
                    133: #define DLPI_DEVDIR            "/dev/" /* Device directory */
                    134: 
                    135: static int dlpiopen(const char *ifname);
                    136: static int dlpiunit (char *ifname);
                    137: static int dlpiinforeq (int fd);
                    138: static int dlpiphysaddrreq (int fd, unsigned long addrtype);
                    139: static int dlpiattachreq (int fd, unsigned long ppa);
                    140: static int dlpibindreq (int fd, unsigned long sap, unsigned long max_conind,
                    141:                        unsigned long service_mode, unsigned long conn_mgmt,
                    142:                        unsigned long xidtest);
                    143: #if defined(UNUSED_DLPI_INTERFACE)
                    144: /* These functions are unused at present, but may be used at a later date.
                    145:  * defined out to avoid compiler warnings about unused static functions.
                    146:  */
                    147: static int dlpidetachreq (int fd);
                    148: static int dlpiunbindreq (int fd);
                    149: #endif
                    150: static int dlpiokack (int fd, char *bufp);
                    151: static int dlpiinfoack (int fd, char *bufp);
                    152: static int dlpiphysaddrack (int fd, char *bufp);
                    153: static int dlpibindack (int fd, char *bufp);
                    154: #if defined(USE_DLPI_SEND) || defined(USE_DLPI_RECEIVE)
                    155: /* These functions are not used if we're only sourcing the get_hw_addr()
                    156:  * function (for USE_SOCKETS).
                    157:  */
                    158: static int dlpiunitdatareq (int fd, unsigned char *addr, int addrlen, 
                    159:                            unsigned long minpri, unsigned long maxpri, 
                    160:                            unsigned char *data, int datalen);
                    161: static int dlpiunitdataind (int fd,
                    162:                            unsigned char *dstaddr,
                    163:                            unsigned long *dstaddrlen,
                    164:                            unsigned char *srcaddr,
                    165:                            unsigned long *srcaddrlen,
                    166:                            unsigned long *grpaddr,
                    167:                            unsigned char *data,
                    168:                            int datalen);
                    169: #endif /* !USE_DLPI_HWADDR: USE_DLPI_SEND || USE_DLPI_RECEIVE */
                    170: static int expected (unsigned long prim, union DL_primitives *dlp, 
                    171:                     int msgflags);
                    172: static int strgetmsg (int fd, struct strbuf *ctlp, struct strbuf *datap,
                    173:                      int *flagsp, char *caller);
                    174: 
                    175: /* Reinitializes the specified interface after an address change.   This
                    176:    is not required for packet-filter APIs. */
                    177: 
                    178: #ifdef USE_DLPI_SEND
                    179: void if_reinitialize_send (info)
                    180:        struct interface_info *info;
                    181: {
                    182: }
                    183: #endif
                    184: 
                    185: #ifdef USE_DLPI_RECEIVE
                    186: void if_reinitialize_receive (info)
                    187:        struct interface_info *info;
                    188: {
                    189: }
                    190: #endif
                    191: 
                    192: /* Called by get_interface_list for each interface that's discovered.
                    193:    Opens a packet filter for each interface and adds it to the select
                    194:    mask. */
                    195: 
                    196: int if_register_dlpi (info)
                    197:        struct interface_info *info;
                    198: {
                    199:        int sock;
                    200:        int unit;
                    201:        long buf [DLPI_MAXDLBUF];
                    202:        union DL_primitives *dlp;
                    203: 
                    204:        dlp = (union DL_primitives *)buf;
                    205: 
                    206:        /* Open a DLPI device */
                    207:        if ((sock = dlpiopen (info -> name)) < 0) {
                    208:            log_fatal ("Can't open DLPI device for %s: %m", info -> name);
                    209:        }
                    210: 
                    211:        /*
                    212:         * Submit a DL_INFO_REQ request, to find the dl_mac_type and 
                    213:          * dl_provider_style
                    214:         */
                    215:        if (dlpiinforeq(sock) < 0 || dlpiinfoack(sock, (char *)buf) < 0) {
                    216:            log_fatal ("Can't get DLPI MAC type for %s: %m", info -> name);
                    217:        } else {
                    218:            switch (dlp -> info_ack.dl_mac_type) {
                    219:              case DL_CSMACD: /* IEEE 802.3 */
                    220:              case DL_ETHER:
                    221:                info -> hw_address.hbuf [0] = HTYPE_ETHER;
                    222:                break;
                    223:              /* adding token ring 5/1999 - mayer@ping.at  */ 
                    224:              case DL_TPR:
                    225:                info -> hw_address.hbuf [0] = HTYPE_IEEE802;
                    226:                break;
                    227:              case DL_FDDI:
                    228:                info -> hw_address.hbuf [0] = HTYPE_FDDI;
                    229:                break;
                    230:              default:
                    231:                log_fatal("%s: unsupported DLPI MAC type %lu", info->name,
                    232:                          (unsigned long)dlp->info_ack.dl_mac_type);
                    233:                break;
                    234:            }
                    235:             /*
                    236:              * copy the sap length and broadcast address of this interface
                    237:              * to interface_info. This fixes nothing but seemed nicer than to
                    238:              * assume -2 and ffffff.
                    239:              */
                    240:             info -> dlpi_sap_length = dlp -> info_ack.dl_sap_length;
                    241:             info -> dlpi_broadcast_addr.hlen = 
                    242:              dlp -> info_ack.dl_brdcst_addr_length;
                    243:             memcpy (info -> dlpi_broadcast_addr.hbuf, 
                    244:              (char *)dlp + dlp -> info_ack.dl_brdcst_addr_offset, 
                    245:              dlp -> info_ack.dl_brdcst_addr_length);
                    246:        }
                    247: 
                    248:        if (dlp -> info_ack.dl_provider_style == DL_STYLE2) {
                    249:            /*
                    250:             * Attach to the device.  If this fails, the device
                    251:             * does not exist.
                    252:             */
                    253:            unit = dlpiunit (info -> name);
                    254:        
                    255:            if (dlpiattachreq (sock, unit) < 0
                    256:                || dlpiokack (sock, (char *)buf) < 0) {
                    257:                log_fatal ("Can't attach DLPI device for %s: %m", info -> name);
                    258:            }
                    259:        }
                    260: 
                    261:        /*
                    262:         * Bind to the IP service access point (SAP), connectionless (CLDLS).
                    263:         */
                    264:        if (dlpibindreq (sock, ETHERTYPE_IP, 0, DL_CLDLS, 0, 0) < 0
                    265:            || dlpibindack (sock, (char *)buf) < 0) {
                    266:            log_fatal ("Can't bind DLPI device for %s: %m", info -> name);
                    267:        }
                    268: 
                    269:        /*
                    270:         * Submit a DL_PHYS_ADDR_REQ request, to find
                    271:         * the hardware address
                    272:         */
                    273:        if (dlpiphysaddrreq (sock, DL_CURR_PHYS_ADDR) < 0
                    274:            || dlpiphysaddrack (sock, (char *)buf) < 0) {
                    275:            log_fatal ("Can't get DLPI hardware address for %s: %m",
                    276:                   info -> name);
                    277:        }
                    278: 
                    279:        info -> hw_address.hlen = dlp -> physaddr_ack.dl_addr_length + 1;
                    280:        memcpy (&info -> hw_address.hbuf [1],
                    281:                (char *)buf + dlp -> physaddr_ack.dl_addr_offset,
                    282:                dlp -> physaddr_ack.dl_addr_length);
                    283: 
                    284: #ifdef USE_DLPI_RAW
                    285:        if (strioctl (sock, DLIOCRAW, INFTIM, 0, 0) < 0) {
                    286:            log_fatal ("Can't set DLPI RAW mode for %s: %m",
                    287:                   info -> name);
                    288:        }
                    289: #endif
                    290: 
                    291: #ifdef USE_DLPI_PFMOD
                    292:        if (ioctl (sock, I_PUSH, "pfmod") < 0) {
                    293:            log_fatal ("Can't push packet filter onto DLPI for %s: %m",
                    294:                   info -> name);
                    295:        }
                    296: #endif
                    297: 
                    298:        return sock;
                    299: }
                    300: 
                    301: #if defined(USE_DLPI_PFMOD) || defined(USE_DLPI_RAW)
                    302: static int
                    303: strioctl (fd, cmd, timeout, len, dp)
                    304: int fd;
                    305: int cmd;
                    306: int timeout;
                    307: int len;
                    308: char *dp;
                    309: {
                    310:     struct strioctl sio;
                    311:     int rslt;
                    312: 
                    313:     sio.ic_cmd = cmd;
                    314:     sio.ic_timout = timeout;
                    315:     sio.ic_len = len;
                    316:     sio.ic_dp = dp;
                    317: 
                    318:     if ((rslt = ioctl (fd, I_STR, &sio)) < 0) {
                    319:        return rslt;
                    320:     } else {
                    321:        return sio.ic_len;
                    322:     }
                    323: }
                    324: #endif /* USE_DPI_PFMOD || USE_DLPI_RAW */
                    325: 
                    326: #ifdef USE_DLPI_SEND
                    327: void if_register_send (info)
                    328:        struct interface_info *info;
                    329: {
                    330:        /* If we're using the DLPI API for sending and receiving,
                    331:           we don't need to register this interface twice. */
                    332: #ifndef USE_DLPI_RECEIVE
                    333: # ifdef USE_DLPI_PFMOD
                    334:        struct packetfilt pf;
                    335: # endif
                    336: 
                    337:        info -> wfdesc = if_register_dlpi (info);
                    338: 
                    339: # ifdef USE_DLPI_PFMOD
                    340:        /* Set up an PFMOD filter that rejects everything... */
                    341:        pf.Pf_Priority = 0;
                    342:        pf.Pf_FilterLen = 1;
                    343:        pf.Pf_Filter [0] = ENF_PUSHZERO;
                    344: 
                    345:        /* Install the filter */
                    346:        if (strioctl (info -> wfdesc, PFIOCSETF, INFTIM,
                    347:                      sizeof (pf), (char *)&pf) < 0) {
                    348:            log_fatal ("Can't set PFMOD send filter on %s: %m", info -> name);
                    349:        }
                    350: 
                    351: # endif /* USE_DLPI_PFMOD */
                    352: #else /* !defined (USE_DLPI_RECEIVE) */
                    353:        /*
                    354:         * If using DLPI for both send and receive, simply re-use
                    355:         * the read file descriptor that was set up earlier.
                    356:         */
                    357:        info -> wfdesc = info -> rfdesc;
                    358: #endif
                    359: 
                    360:         if (!quiet_interface_discovery)
                    361:                log_info ("Sending on   DLPI/%s/%s%s%s",
                    362:                      info -> name,
                    363:                      print_hw_addr (info -> hw_address.hbuf [0],
                    364:                                     info -> hw_address.hlen - 1,
                    365:                                     &info -> hw_address.hbuf [1]),
                    366:                      (info -> shared_network ? "/" : ""),
                    367:                      (info -> shared_network ?
                    368:                       info -> shared_network -> name : ""));
                    369: 
                    370: #ifdef DLPI_FIRST_SEND_WAIT
                    371: /* See the implementation notes at the beginning of this file */
                    372: # ifdef USE_DLPI_RECEIVE
                    373:        sleep (DLPI_FIRST_SEND_WAIT - (DLPI_FIRST_SEND_WAIT / 2));
                    374: # else
                    375:        sleep (DLPI_FIRST_SEND_WAIT);
                    376: # endif
                    377: #endif
                    378: }
                    379: 
                    380: void if_deregister_send (info)
                    381:        struct interface_info *info;
                    382: {
                    383:        /* If we're using the DLPI API for sending and receiving,
                    384:           we don't need to register this interface twice. */
                    385: #ifndef USE_DLPI_RECEIVE
                    386:        close (info -> wfdesc);
                    387: #endif
                    388:        info -> wfdesc = -1;
                    389: 
                    390:         if (!quiet_interface_discovery)
                    391:                log_info ("Disabling output on DLPI/%s/%s%s%s",
                    392:                      info -> name,
                    393:                      print_hw_addr (info -> hw_address.hbuf [0],
                    394:                                     info -> hw_address.hlen - 1,
                    395:                                     &info -> hw_address.hbuf [1]),
                    396:                      (info -> shared_network ? "/" : ""),
                    397:                      (info -> shared_network ?
                    398:                       info -> shared_network -> name : ""));
                    399: }
                    400: #endif /* USE_DLPI_SEND */
                    401: 
                    402: #ifdef USE_DLPI_RECEIVE
                    403: /* Packet filter program...
                    404:    XXX Changes to the filter program may require changes to the constant
                    405:    offsets used in if_register_send to patch the NIT program! XXX */
                    406: 
                    407: void if_register_receive (info)
                    408:        struct interface_info *info;
                    409: {
                    410: #ifdef USE_DLPI_PFMOD
                    411:        struct packetfilt pf;
                    412:         struct ip iphdr;
                    413:         u_int16_t offset;
                    414: #endif
                    415: 
                    416:        /* Open a DLPI device and hang it on this interface... */
                    417:        info -> rfdesc = if_register_dlpi (info);
                    418: 
                    419: #ifdef USE_DLPI_PFMOD
                    420:        /* Set up the PFMOD filter program. */
                    421:        /* XXX Unlike the BPF filter program, this one won't work if the
                    422:           XXX IP packet is fragmented or if there are options on the IP
                    423:           XXX header. */
                    424:        pf.Pf_Priority = 0;
                    425:        pf.Pf_FilterLen = 0;
                    426: 
                    427: #if defined (USE_DLPI_RAW)
                    428: # define ETHER_H_PREFIX (14) /* sizeof (ethernet_header) */
                    429:     /*
                    430:      * ethertype == ETHERTYPE_IP
                    431:      */
                    432:     offset = 12;
                    433:     pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2);
                    434:     pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_CAND;
                    435:     pf.Pf_Filter [pf.Pf_FilterLen++] = htons (ETHERTYPE_IP);
                    436: # else
                    437: # define ETHER_H_PREFIX (0)
                    438: # endif /* USE_DLPI_RAW */
                    439:        /*
                    440:         * The packets that will be received on this file descriptor
                    441:         * will be IP packets (due to the SAP that was specified in
                    442:         * the dlbind call).  There will be no ethernet header.
                    443:         * Therefore, setup the packet filter to check the protocol
                    444:         * field for UDP, and the destination port number equal
                    445:         * to the local port.  All offsets are relative to the start
                    446:         * of an IP packet.
                    447:         */
                    448: 
                    449:         /*
                    450:          * BOOTPS destination port
                    451:          */
                    452:         offset = ETHER_H_PREFIX + sizeof (iphdr) + sizeof (u_int16_t);
                    453:         pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2);
                    454:         pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_CAND;
                    455:         pf.Pf_Filter [pf.Pf_FilterLen++] = local_port;
                    456: 
                    457:         /*
                    458:          * protocol should be udp. this is a byte compare, test for
                    459:          * endianess.
                    460:          */
                    461:         offset = ETHER_H_PREFIX + ((u_int8_t *)&(iphdr.ip_p) - (u_int8_t *)&iphdr);
                    462:         pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2);
                    463:         pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_AND;
                    464:         pf.Pf_Filter [pf.Pf_FilterLen++] = htons (0x00FF);
                    465:         pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_CAND;
                    466:       pf.Pf_Filter [pf.Pf_FilterLen++] = htons (IPPROTO_UDP);
                    467: 
                    468:        /* Install the filter... */
                    469:        if (strioctl (info -> rfdesc, PFIOCSETF, INFTIM,
                    470:                      sizeof (pf), (char *)&pf) < 0) {
                    471:            log_fatal ("Can't set PFMOD receive filter on %s: %m", info -> name);
                    472:        }
                    473: #endif /* USE_DLPI_PFMOD */
                    474: 
                    475:         if (!quiet_interface_discovery)
                    476:                log_info ("Listening on DLPI/%s/%s%s%s",
                    477:                      info -> name,
                    478:                      print_hw_addr (info -> hw_address.hbuf [0],
                    479:                                     info -> hw_address.hlen - 1,
                    480:                                     &info -> hw_address.hbuf [1]),
                    481:                      (info -> shared_network ? "/" : ""),
                    482:                      (info -> shared_network ?
                    483:                       info -> shared_network -> name : ""));
                    484: 
                    485: #ifdef DLPI_FIRST_SEND_WAIT
                    486: /* See the implementation notes at the beginning of this file */
                    487: # ifdef USE_DLPI_SEND
                    488:        sleep (DLPI_FIRST_SEND_WAIT / 2);
                    489: # else
                    490:        sleep (DLPI_FIRST_SEND_WAIT);
                    491: # endif
                    492: #endif
                    493: }
                    494: 
                    495: void if_deregister_receive (info)
                    496:        struct interface_info *info;
                    497: {
                    498:        /* If we're using the DLPI API for sending and receiving,
                    499:           we don't need to register this interface twice. */
                    500: #ifndef USE_DLPI_SEND
                    501:        close (info -> rfdesc);
                    502: #endif
                    503:        info -> rfdesc = -1;
                    504: 
                    505:         if (!quiet_interface_discovery)
                    506:                log_info ("Disabling input on DLPI/%s/%s%s%s",
                    507:                      info -> name,
                    508:                      print_hw_addr (info -> hw_address.hbuf [0],
                    509:                                     info -> hw_address.hlen - 1,
                    510:                                     &info -> hw_address.hbuf [1]),
                    511:                      (info -> shared_network ? "/" : ""),
                    512:                      (info -> shared_network ?
                    513:                       info -> shared_network -> name : ""));
                    514: }
                    515: #endif /* USE_DLPI_RECEIVE */
                    516: 
                    517: #ifdef USE_DLPI_SEND
                    518: ssize_t send_packet (interface, packet, raw, len, from, to, hto)
                    519:        struct interface_info *interface;
                    520:        struct packet *packet;
                    521:        struct dhcp_packet *raw;
                    522:        size_t len;
                    523:        struct in_addr from;
                    524:        struct sockaddr_in *to;
                    525:        struct hardware *hto;
                    526: {
                    527: #ifdef USE_DLPI_RAW
                    528:        double hh [32];
                    529: #endif
                    530:        double ih [1536 / sizeof (double)];
                    531:        unsigned char *dbuf = (unsigned char *)ih;
                    532:        unsigned dbuflen;
                    533:        unsigned char dstaddr [DLPI_MAXDLADDR];
                    534:        unsigned addrlen;
                    535:        int result;
                    536:        int fudge;
                    537: 
                    538:        if (!strcmp (interface -> name, "fallback"))
                    539:                return send_fallback (interface, packet, raw,
                    540:                                      len, from, to, hto);
                    541: 
                    542:        dbuflen = 0;
                    543: 
                    544:        /* Assemble the headers... */
                    545: #ifdef USE_DLPI_RAW
                    546:        assemble_hw_header (interface, (unsigned char *)hh, &dbuflen, hto);
                    547:       if (dbuflen > sizeof hh)
                    548:               log_fatal ("send_packet: hh buffer too small.\n");
                    549:        fudge = dbuflen % 4; /* IP header must be word-aligned. */
                    550:        memcpy (dbuf + fudge, (unsigned char *)hh, dbuflen);
                    551:        dbuflen += fudge;
                    552: #else
                    553:        fudge = 0;
                    554: #endif
                    555:        assemble_udp_ip_header (interface, dbuf, &dbuflen, from.s_addr,
                    556:                                to -> sin_addr.s_addr, to -> sin_port,
                    557:                                (unsigned char *)raw, len);
                    558: 
                    559:        /* Copy the data into the buffer (yuk). */
                    560:        memcpy (dbuf + dbuflen, raw, len);
                    561:        dbuflen += len;
                    562: 
                    563: #ifdef USE_DLPI_RAW
                    564:        result = write (interface -> wfdesc, dbuf + fudge, dbuflen - fudge);
                    565: #else
                    566: 
                    567:        /*
                    568:          * Setup the destination address (DLSAP) in dstaddr 
                    569:          *
                    570:          * If sap_length < 0 we must deliver the DLSAP as phys+sap. 
                    571:          * If sap_length > 0 we must deliver the DLSAP as sap+phys.
                    572:          *
                    573:          * sap = Service Access Point == ETHERTYPE_IP
                    574:          * sap + datalink address is called DLSAP in dlpi speak.
                    575:          */
                    576:         { /* ENCODE DLSAP */
                    577:           unsigned char phys [DLPI_MAXDLADDR];
                    578:           unsigned char sap [4];
                    579:           int sap_len = interface -> dlpi_sap_length;
                    580:           int phys_len = interface -> hw_address.hlen - 1;
                    581: 
                    582:           /* sap = htons (ETHERTYPE_IP) kludge */
                    583:           memset (sap, 0, sizeof (sap));
                    584: # if (BYTE_ORDER == LITTLE_ENDIAN)
                    585:           sap [0] = 0x00;
                    586:           sap [1] = 0x08;
                    587: # else
                    588:           sap [0] = 0x08;
                    589:           sap [1] = 0x00;
                    590: # endif
                    591: 
                    592:         if (hto && hto -> hlen == interface -> hw_address.hlen)
                    593:              memcpy ( phys, (char *) &hto -> hbuf [1], phys_len);
                    594:           else 
                    595:              memcpy ( phys, interface -> dlpi_broadcast_addr.hbuf, 
                    596:               interface -> dlpi_broadcast_addr.hlen);
                    597:            
                    598:           if (sap_len < 0) { 
                    599:              memcpy ( dstaddr, phys, phys_len);
                    600:              memcpy ( (char *) &dstaddr [phys_len], sap, ABS (sap_len));
                    601:           }
                    602:           else {
                    603:              memcpy ( dstaddr, (void *) sap, sap_len);
                    604:              memcpy ( (char *) &dstaddr [sap_len], phys, phys_len);
                    605:           }
                    606:         addrlen = phys_len + ABS (sap_len);
                    607:       } /* ENCODE DLSAP */
                    608: 
                    609:        result = dlpiunitdatareq (interface -> wfdesc, dstaddr, addrlen,
                    610:                                  0, 0, dbuf, dbuflen);
                    611: #endif /* USE_DLPI_RAW */
                    612:        if (result < 0)
                    613:                log_error ("send_packet: %m");
                    614:        return result;
                    615: }
                    616: #endif /* USE_DLPI_SEND */
                    617: 
                    618: #ifdef USE_DLPI_RECEIVE
                    619: ssize_t receive_packet (interface, buf, len, from, hfrom)
                    620:        struct interface_info *interface;
                    621:        unsigned char *buf;
                    622:        size_t len;
                    623:        struct sockaddr_in *from;
                    624:        struct hardware *hfrom;
                    625: {
                    626:        unsigned char dbuf [1536];
                    627:        unsigned char srcaddr [DLPI_MAXDLADDR];
                    628:        unsigned long srcaddrlen;
                    629:        int length = 0;
                    630:        int offset = 0;
                    631:        int bufix = 0;
                    632:        unsigned paylen;
                    633:        
                    634: #ifdef USE_DLPI_RAW
                    635:        length = read (interface -> rfdesc, dbuf, sizeof (dbuf));
                    636: #else  
                    637:        length = dlpiunitdataind (interface -> rfdesc, (unsigned char *)NULL,
                    638:                                  (unsigned long *)NULL, srcaddr, &srcaddrlen,
                    639:                                  (unsigned long *)NULL, dbuf, sizeof (dbuf));
                    640: #endif
                    641: 
                    642:        if (length <= 0) {
                    643:            log_error("receive_packet: %m");
                    644:            return length;
                    645:        }
                    646: 
                    647: # if !defined (USE_DLPI_RAW)
                    648:         /*
                    649:          * Copy the sender's hw address into hfrom
                    650:          * If sap_len < 0 the DLSAP is as phys+sap.
                    651:          * If sap_len > 0 the DLSAP is as sap+phys.
                    652:          *
                    653:          * sap is discarded here.
                    654:          */
                    655:         { /* DECODE DLSAP */
                    656:           int sap_len = interface -> dlpi_sap_length;
                    657:           int phys_len = interface -> hw_address.hlen - 1;
                    658: 
                    659:           if (hfrom && (srcaddrlen == ABS (sap_len) + phys_len )) {
                    660:             hfrom -> hbuf [0] = interface -> hw_address.hbuf [0];
                    661:             hfrom -> hlen = interface -> hw_address.hlen;
                    662:             
                    663:             if (sap_len < 0) {
                    664:               memcpy ((char *) &hfrom -> hbuf [1], srcaddr, phys_len);
                    665:             }
                    666:             else {
                    667:               memcpy((char *)&hfrom->hbuf[1], srcaddr + sap_len, phys_len);
                    668:             }
                    669:           } 
                    670:           else if (hfrom) {
                    671:             memset (hfrom, '\0', sizeof *hfrom);
                    672:           }
                    673:         } /* DECODE_DLSAP */
                    674: 
                    675: # endif /* !defined (USE_DLPI_RAW) */
                    676: 
                    677:        /* Decode the IP and UDP headers... */
                    678:        bufix = 0;
                    679: #ifdef USE_DLPI_RAW
                    680:        /* Decode the physical header... */
                    681:        offset = decode_hw_header (interface, dbuf, bufix, hfrom);
                    682: 
                    683:        /* If a physical layer checksum failed (dunno of any
                    684:           physical layer that supports this, but WTH), skip this
                    685:           packet. */
                    686:        if (offset < 0) {
                    687:                return 0;
                    688:        }
                    689:        bufix += offset;
                    690:        length -= offset;
                    691: #endif
                    692:        offset = decode_udp_ip_header (interface, dbuf, bufix,
                    693:                                       from, length, &paylen);
                    694: 
                    695:        /*
                    696:         * If the IP or UDP checksum was bad, skip the packet...
                    697:         *
                    698:         * Note: this happens all the time when writing packets via the
                    699:         * fallback socket.  The packet received by streams does not have
                    700:         * the IP or UDP checksums filled in, as those are calculated by
                    701:         * the hardware.
                    702:         */
                    703:        if (offset < 0) {
                    704:                return 0;
                    705:        }
                    706: 
                    707:        bufix += offset;
                    708:        length -= offset;
                    709: 
                    710:        if (length < paylen)
                    711:                log_fatal("Internal inconsistency at %s:%d.", MDL);
                    712: 
                    713:        /* Copy out the data in the packet... */
                    714:        memcpy(buf, &dbuf [bufix], paylen);
                    715:        return paylen;
                    716: }
                    717: #endif
                    718: 
                    719: /* Common DLPI routines ...
                    720:  *
                    721:  * Written by Eric James Negaard, <lmdejn@lmd.ericsson.se>
                    722:  *
                    723:  * Based largely in part to the example code contained in the document
                    724:  * "How to Use the STREAMS Data Link Provider Interface (DLPI)", written
                    725:  * by Neal Nuckolls of SunSoft Internet Engineering.
                    726:  * 
                    727:  * This code has been developed and tested on sparc-based machines running
                    728:  * SunOS 5.5.1, with le and hme network interfaces.  It should be pretty
                    729:  * generic, though.
                    730:  * 
                    731:  * The usual disclaimers apply.  This code works for me.  Don't blame me
                    732:  * if it makes your machine or network go down in flames.  That taken
                    733:  * into consideration, use this code as you wish.  If you make usefull
                    734:  * modifications I'd appreciate hearing about it.
                    735:  */
                    736: 
                    737: #define DLPI_MAXWAIT           15      /* Max timeout */
                    738: 
                    739: 
                    740: /*
                    741:  * Parse an interface name and extract the unit number
                    742:  */
                    743: 
                    744: static int dlpiunit (ifname)
                    745:        char *ifname;
                    746: {
                    747:        char *cp;
                    748:        int unit;
                    749:        
                    750:        if (!ifname) {
                    751:                return 0;
                    752:        }
                    753:        
                    754:        /* Advance to the end of the name */
                    755:        cp = ifname;
                    756:        while (*cp) cp++;
                    757:        /* Back up to the start of the first digit */
                    758:        while ((*(cp-1) >= '0' && *(cp-1) <= '9') || *(cp - 1) == ':') cp--;
                    759:        
                    760:        /* Convert the unit number */
                    761:        unit = 0;
                    762:        while (*cp >= '0' && *cp <= '9') {
                    763:                unit *= 10;
                    764:                unit += (*cp++ - '0');
                    765:        }
                    766:        
                    767:        return unit;
                    768: }
                    769: 
                    770: /*
                    771:  * dlpiopen - open the DLPI device for a given interface name
                    772:  */
                    773: static int
                    774: dlpiopen(const char *ifname) {
                    775:        char devname [50];
                    776:        char *dp;
                    777:        const char *cp, *ep;
                    778:        
                    779:        if (!ifname) {
                    780:                return -1;
                    781:        }
                    782:        
                    783:        /* Open a DLPI device */
                    784:        if (*ifname == '/') {
                    785:                dp = devname;
                    786:        } else {
                    787:                /* Prepend the device directory */
                    788:                memcpy (devname, DLPI_DEVDIR, strlen (DLPI_DEVDIR));
                    789:                dp = &devname [strlen (DLPI_DEVDIR)];
                    790:        }
                    791: 
                    792:        /* Find the end of the interface name */
                    793:        ep = cp = ifname;
                    794:        while (*ep)
                    795:                ep++;
                    796:        /* And back up to the first digit (unit number) */
                    797:        while ((*(ep - 1) >= '0' && *(ep - 1) <= '9') || *(ep - 1) == ':')
                    798:                ep--;
                    799:        
                    800:        /* Copy everything up to the unit number */
                    801:        while (cp < ep) {
                    802:                *dp++ = *cp++;
                    803:        }
                    804:        *dp = '\0';
                    805:        
                    806:        return open (devname, O_RDWR, 0);
                    807: }
                    808: 
                    809: /*
                    810:  * dlpiinforeq - request information about the data link provider.
                    811:  */
                    812: 
                    813: static int dlpiinforeq (fd)
                    814:        int fd;
                    815: {
                    816:        dl_info_req_t info_req;
                    817:        struct strbuf ctl;
                    818:        int flags;
                    819:        
                    820:        info_req.dl_primitive = DL_INFO_REQ;
                    821:        
                    822:        ctl.maxlen = 0;
                    823:        ctl.len = sizeof (info_req);
                    824:        ctl.buf = (char *)&info_req;
                    825:        
                    826:        flags = RS_HIPRI;
                    827:        
                    828:        return putmsg (fd, &ctl, (struct strbuf *)NULL, flags);
                    829: }
                    830: 
                    831: /*
                    832:  * dlpiphysaddrreq - request the current physical address.
                    833:  */
                    834: static int dlpiphysaddrreq (fd, addrtype)
                    835:        int fd;
                    836:        unsigned long addrtype;
                    837: {
                    838:        dl_phys_addr_req_t physaddr_req;
                    839:        struct strbuf ctl;
                    840:        int flags;
                    841:        
                    842:        physaddr_req.dl_primitive = DL_PHYS_ADDR_REQ;
                    843:        physaddr_req.dl_addr_type = addrtype;
                    844:        
                    845:        ctl.maxlen = 0;
                    846:        ctl.len = sizeof (physaddr_req);
                    847:        ctl.buf = (char *)&physaddr_req;
                    848:        
                    849:        flags = RS_HIPRI;
                    850:        
                    851:        return putmsg (fd, &ctl, (struct strbuf *)NULL, flags);
                    852: }
                    853: 
                    854: /*
                    855:  * dlpiattachreq - send a request to attach to a specific unit.
                    856:  */
                    857: static int dlpiattachreq (fd, ppa)
                    858:        unsigned long ppa;
                    859:        int fd;
                    860: {
                    861:        dl_attach_req_t attach_req;
                    862:        struct strbuf ctl;
                    863:        int flags;
                    864:        
                    865:        attach_req.dl_primitive = DL_ATTACH_REQ;
                    866:        attach_req.dl_ppa = ppa;
                    867:        
                    868:        ctl.maxlen = 0;
                    869:        ctl.len = sizeof (attach_req);
                    870:        ctl.buf = (char *)&attach_req;
                    871:        
                    872:        flags = 0;
                    873:        
                    874:        return putmsg (fd, &ctl, (struct strbuf*)NULL, flags);
                    875: }
                    876: 
                    877: /*
                    878:  * dlpibindreq - send a request to bind to a specific SAP address.
                    879:  */
                    880: static int dlpibindreq (fd, sap, max_conind, service_mode, conn_mgmt, xidtest)
                    881:        unsigned long sap;
                    882:        unsigned long max_conind;
                    883:        unsigned long service_mode;
                    884:        unsigned long conn_mgmt;
                    885:        unsigned long xidtest;
                    886:        int fd;
                    887: {
                    888:        dl_bind_req_t bind_req;
                    889:        struct strbuf ctl;
                    890:        int flags;
                    891:        
                    892:        bind_req.dl_primitive = DL_BIND_REQ;
                    893:        bind_req.dl_sap = sap;
                    894:        bind_req.dl_max_conind = max_conind;
                    895:        bind_req.dl_service_mode = service_mode;
                    896:        bind_req.dl_conn_mgmt = conn_mgmt;
                    897:        bind_req.dl_xidtest_flg = xidtest;
                    898:        
                    899:        ctl.maxlen = 0;
                    900:        ctl.len = sizeof (bind_req);
                    901:        ctl.buf = (char *)&bind_req;
                    902:        
                    903:        flags = 0;
                    904:        
                    905:        return putmsg (fd, &ctl, (struct strbuf*)NULL, flags);
                    906: }
                    907: 
                    908: #if defined(UNUSED_DLPI_INTERFACE)
                    909: /*
                    910:  * dlpiunbindreq - send a request to unbind.  This function is not actually
                    911:  *     used by ISC DHCP, but is included for completeness in case it is
                    912:  *     ever required for new work.
                    913:  */
                    914: static int dlpiunbindreq (fd)
                    915:        int fd;
                    916: {
                    917:        dl_unbind_req_t unbind_req;
                    918:        struct strbuf ctl;
                    919:        int flags;
                    920:        
                    921:        unbind_req.dl_primitive = DL_UNBIND_REQ;
                    922:        
                    923:        ctl.maxlen = 0;
                    924:        ctl.len = sizeof (unbind_req);
                    925:        ctl.buf = (char *)&unbind_req;
                    926:        
                    927:        flags = 0;
                    928:        
                    929:        return putmsg (fd, &ctl, (struct strbuf*)NULL, flags);
                    930: }
                    931: 
                    932: 
                    933: /*
                    934:  * dlpidetachreq - send a request to detach.  This function is not actually
                    935:  *     used by ISC DHCP, but is included for completeness in case it is
                    936:  *     ever required for new work.
                    937:  */
                    938: static int dlpidetachreq (fd)
                    939:        int fd;
                    940: {
                    941:        dl_detach_req_t detach_req;
                    942:        struct strbuf ctl;
                    943:        int flags;
                    944:        
                    945:        detach_req.dl_primitive = DL_DETACH_REQ;
                    946:        
                    947:        ctl.maxlen = 0;
                    948:        ctl.len = sizeof (detach_req);
                    949:        ctl.buf = (char *)&detach_req;
                    950:        
                    951:        flags = 0;
                    952:        
                    953:        return putmsg (fd, &ctl, (struct strbuf*)NULL, flags);
                    954: }
                    955: #endif /* UNUSED_DLPI_INTERFACE */
                    956: 
                    957: 
                    958: /*
                    959:  * dlpibindack - receive an ack to a dlbindreq.
                    960:  */
                    961: static int dlpibindack (fd, bufp)
                    962:        char *bufp;
                    963:        int fd;
                    964: {
                    965:        union DL_primitives *dlp;
                    966:        struct strbuf ctl;
                    967:        int flags;
                    968:        
                    969:        ctl.maxlen = DLPI_MAXDLBUF;
                    970:        ctl.len = 0;
                    971:        ctl.buf = bufp;
                    972: 
                    973:        if (strgetmsg (fd, &ctl,
                    974:                       (struct strbuf*)NULL, &flags, "dlpibindack") < 0) {
                    975:                return -1;
                    976:        }
                    977:        
                    978:        dlp = (union DL_primitives *)ctl.buf;
                    979:        
                    980:        if (expected (DL_BIND_ACK, dlp, flags) == -1) {
                    981:                return -1;
                    982:        }
                    983:        
                    984:        if (ctl.len < sizeof (dl_bind_ack_t)) {
                    985:                /* Returned structure is too short */
                    986:                return -1;
                    987:        }
                    988: 
                    989:        return 0;
                    990: }
                    991: 
                    992: /*
                    993:  * dlpiokack - general acknowledgement reception.
                    994:  */
                    995: static int dlpiokack (fd, bufp)
                    996:        char *bufp;
                    997:        int fd;
                    998: {
                    999:        union DL_primitives *dlp;
                   1000:        struct strbuf ctl;
                   1001:        int flags;
                   1002:        
                   1003:        ctl.maxlen = DLPI_MAXDLBUF;
                   1004:        ctl.len = 0;
                   1005:        ctl.buf = bufp;
                   1006:        
                   1007:        if (strgetmsg (fd, &ctl,
                   1008:                       (struct strbuf*)NULL, &flags, "dlpiokack") < 0) {
                   1009:                return -1;
                   1010:        }
                   1011:        
                   1012:        dlp = (union DL_primitives *)ctl.buf;
                   1013:        
                   1014:        if (expected (DL_OK_ACK, dlp, flags) == -1) {
                   1015:                return -1;
                   1016:        }
                   1017:        
                   1018:        if (ctl.len < sizeof (dl_ok_ack_t)) {
                   1019:                /* Returned structure is too short */
                   1020:                return -1;
                   1021:        }
                   1022:        
                   1023:        return 0;
                   1024: }
                   1025: 
                   1026: /*
                   1027:  * dlpiinfoack - receive an ack to a dlinforeq.
                   1028:  */
                   1029: static int dlpiinfoack (fd, bufp)
                   1030:        char *bufp;
                   1031:        int fd;
                   1032: {
                   1033:        union DL_primitives *dlp;
                   1034:        struct strbuf ctl;
                   1035:        int flags;
                   1036:        
                   1037:        ctl.maxlen = DLPI_MAXDLBUF;
                   1038:        ctl.len = 0;
                   1039:        ctl.buf = bufp;
                   1040:        
                   1041:        if (strgetmsg (fd, &ctl, (struct strbuf *)NULL, &flags,
                   1042:                       "dlpiinfoack") < 0) {
                   1043:                return -1;
                   1044:        }
                   1045:        
                   1046:        dlp = (union DL_primitives *) ctl.buf;
                   1047:        
                   1048:        if (expected (DL_INFO_ACK, dlp, flags) == -1) {
                   1049:                return -1;
                   1050:        }
                   1051:        
                   1052:        if (ctl.len < sizeof (dl_info_ack_t)) {
                   1053:                /* Returned structure is too short */
                   1054:                return -1;
                   1055:        }
                   1056:        
                   1057:        return 0;
                   1058: }
                   1059: 
                   1060: /*
                   1061:  * dlpiphysaddrack - receive an ack to a dlpiphysaddrreq.
                   1062:  */
                   1063: int dlpiphysaddrack (fd, bufp)
                   1064:        char *bufp;
                   1065:        int fd;
                   1066: {
                   1067:        union DL_primitives *dlp;
                   1068:        struct strbuf ctl;
                   1069:        int flags;
                   1070:        
                   1071:        ctl.maxlen = DLPI_MAXDLBUF;
                   1072:        ctl.len = 0;
                   1073:        ctl.buf = bufp;
                   1074:        
                   1075:        if (strgetmsg (fd, &ctl, (struct strbuf *)NULL, &flags,
                   1076:                       "dlpiphysaddrack") < 0) {
                   1077:                return -1;
                   1078:        }
                   1079: 
                   1080:        dlp = (union DL_primitives *)ctl.buf;
                   1081:        
                   1082:        if (expected (DL_PHYS_ADDR_ACK, dlp, flags) == -1) {
                   1083:                return -1;
                   1084:        }
                   1085: 
                   1086:        if (ctl.len < sizeof (dl_phys_addr_ack_t)) {
                   1087:                /* Returned structure is too short */
                   1088:                return -1;
                   1089:        }
                   1090:        
                   1091:        return 0;
                   1092: }
                   1093: 
                   1094: #if defined(USE_DLPI_SEND) || defined(USE_DLPI_RECEIVE)
                   1095: int dlpiunitdatareq (fd, addr, addrlen, minpri, maxpri, dbuf, dbuflen)
                   1096:        int fd;
                   1097:        unsigned char *addr;
                   1098:        int addrlen;
                   1099:        unsigned long minpri;
                   1100:        unsigned long maxpri;
                   1101:        unsigned char *dbuf;
                   1102:        int dbuflen;
                   1103: {
                   1104:        long buf [DLPI_MAXDLBUF];
                   1105:        union DL_primitives *dlp;
                   1106:        struct strbuf ctl, data;
                   1107:        
                   1108:        /* Set up the control information... */
                   1109:        dlp = (union DL_primitives *)buf;
                   1110:        dlp -> unitdata_req.dl_primitive = DL_UNITDATA_REQ;
                   1111:        dlp -> unitdata_req.dl_dest_addr_length = addrlen;
                   1112:        dlp -> unitdata_req.dl_dest_addr_offset = sizeof (dl_unitdata_req_t);
                   1113:        dlp -> unitdata_req.dl_priority.dl_min = minpri;
                   1114:        dlp -> unitdata_req.dl_priority.dl_max = maxpri;
                   1115: 
                   1116:        /* Append the destination address */
                   1117:        memcpy ((char *)buf + dlp -> unitdata_req.dl_dest_addr_offset,
                   1118:                addr, addrlen);
                   1119:        
                   1120:        ctl.maxlen = 0;
                   1121:        ctl.len = dlp -> unitdata_req.dl_dest_addr_offset + addrlen;
                   1122:        ctl.buf = (char *)buf;
                   1123: 
                   1124:        data.maxlen = 0;
                   1125:        data.buf = (char *)dbuf;
                   1126:        data.len = dbuflen;
                   1127: 
                   1128:        /* Send the packet down the wire... */
                   1129:        return putmsg (fd, &ctl, &data, 0);
                   1130: }
                   1131: 
                   1132: static int dlpiunitdataind (fd, daddr, daddrlen,
                   1133:                            saddr, saddrlen, grpaddr, dbuf, dlen)
                   1134:        int fd;
                   1135:        unsigned char *daddr;
                   1136:        unsigned long *daddrlen;
                   1137:        unsigned char *saddr;
                   1138:        unsigned long *saddrlen;
                   1139:        unsigned long *grpaddr;
                   1140:        unsigned char *dbuf;
                   1141:        int dlen;
                   1142: {
                   1143:        long buf [DLPI_MAXDLBUF];
                   1144:        union DL_primitives *dlp;
                   1145:        struct strbuf ctl, data;
                   1146:        int flags = 0;
                   1147:        int result;
                   1148: 
                   1149:        /* Set up the msg_buf structure... */
                   1150:        dlp = (union DL_primitives *)buf;
                   1151:        dlp -> unitdata_ind.dl_primitive = DL_UNITDATA_IND;
                   1152: 
                   1153:        ctl.maxlen = DLPI_MAXDLBUF;
                   1154:        ctl.len = 0;
                   1155:        ctl.buf = (char *)buf;
                   1156: 
                   1157:        data.maxlen = dlen;
                   1158:        data.len = 0;
                   1159:        data.buf = (char *)dbuf;
                   1160: 
                   1161:        result = getmsg (fd, &ctl, &data, &flags);
                   1162: 
                   1163:        if (result < 0) {
                   1164:                log_debug("dlpiunitdataind: %m");
                   1165:                return -1;
                   1166:        }
                   1167: 
                   1168:        if (ctl.len < sizeof (dl_unitdata_ind_t) ||
                   1169:            dlp -> unitdata_ind.dl_primitive != DL_UNITDATA_IND) {
                   1170:                return -1;
                   1171:        }
                   1172: 
                   1173:        if (data.len <= 0) {
                   1174:                return data.len;
                   1175:        }
                   1176: 
                   1177:        /* Copy sender info */
                   1178:        if (saddr) {
                   1179:                memcpy (saddr,
                   1180:                        (char *)buf + dlp -> unitdata_ind.dl_src_addr_offset,
                   1181:                        dlp -> unitdata_ind.dl_src_addr_length);
                   1182:        }
                   1183:        if (saddrlen) {
                   1184:                *saddrlen = dlp -> unitdata_ind.dl_src_addr_length;
                   1185:        }
                   1186: 
                   1187:        /* Copy destination info */
                   1188:        if (daddr) {
                   1189:                memcpy (daddr,
                   1190:                        (char *)buf + dlp -> unitdata_ind.dl_dest_addr_offset,
                   1191:                        dlp -> unitdata_ind.dl_dest_addr_length);
                   1192:        }
                   1193:        if (daddrlen) {
                   1194:                *daddrlen = dlp -> unitdata_ind.dl_dest_addr_length;
                   1195:        }
                   1196: 
                   1197:        if (grpaddr) {
                   1198:                *grpaddr = dlp -> unitdata_ind.dl_group_address;
                   1199:        }
                   1200: 
                   1201:        return data.len;
                   1202: }
                   1203: #endif /* !USE_DLPI_HWADDR: USE_DLPI_RECEIVE || USE_DLPI_SEND */
                   1204: 
                   1205: /*
                   1206:  * expected - see if we got what we wanted.
                   1207:  */
                   1208: static int expected (prim, dlp, msgflags)
                   1209:        unsigned long prim;
                   1210:        union DL_primitives *dlp;
                   1211:        int msgflags;
                   1212: {
                   1213:        if (msgflags != RS_HIPRI) {
                   1214:                /* Message was not M_PCPROTO */
                   1215:                return -1;
                   1216:        }
                   1217: 
                   1218:        if (dlp->dl_primitive != prim) {
                   1219:                /* Incorrect/unexpected return message */
                   1220:                return -1;
                   1221:        }
                   1222:        
                   1223:        return 0;
                   1224: }
                   1225: 
                   1226: /*
                   1227:  * strgetmsg - get a message from a stream, with timeout.
                   1228:  */
                   1229: static int strgetmsg (fd, ctlp, datap, flagsp, caller)
                   1230:        struct strbuf *ctlp, *datap;
                   1231:        char *caller;
                   1232:        int *flagsp;
                   1233:        int fd;
                   1234: {
                   1235:        int result;
                   1236:        struct pollfd pfd;
                   1237:        int count;
                   1238:        time_t now;
                   1239:        time_t starttime;
                   1240:        int to_msec;
                   1241:        
                   1242:        pfd.fd = fd;
                   1243:        pfd.events = POLLPRI;   /* We're only interested in knowing
                   1244:                                 * when we can receive the next high
                   1245:                                 * priority message.
                   1246:                                 */
                   1247:        pfd.revents = 0;
                   1248: 
                   1249:        now = time (&starttime);
                   1250:        while (now <= starttime + DLPI_MAXWAIT) {
                   1251:                to_msec = ((starttime + DLPI_MAXWAIT) - now) * 1000;
                   1252:                count = poll (&pfd, 1, to_msec);
                   1253:                
                   1254:                if (count == 0) {
                   1255:                        /* log_fatal ("strgetmsg: timeout"); */
                   1256:                        return -1;
                   1257:                } else if (count < 0) {
                   1258:                        if (errno == EAGAIN || errno == EINTR) {
                   1259:                                time (&now);
                   1260:                                continue;
                   1261:                        } else {
                   1262:                                /* log_fatal ("poll: %m"); */
                   1263:                                return -1;
                   1264:                        }
                   1265:                } else {
                   1266:                        break;
                   1267:                }
                   1268:        }
                   1269: 
                   1270:        /*
                   1271:         * Set flags argument and issue getmsg ().
                   1272:         */
                   1273:        *flagsp = 0;
                   1274:        if ((result = getmsg (fd, ctlp, datap, flagsp)) < 0) {
                   1275:                return result;
                   1276:        }
                   1277: 
                   1278:        /*
                   1279:         * Check for MOREDATA and/or MORECTL.
                   1280:         */
                   1281:        if (result & (MORECTL|MOREDATA)) {
                   1282:                return -1;
                   1283:        }
                   1284: 
                   1285:        /*
                   1286:         * Check for at least sizeof (long) control data portion.
                   1287:         */
                   1288:        if (ctlp -> len < sizeof (long)) {
                   1289:                return -1;
                   1290:        }
                   1291: 
                   1292:        return 0;
                   1293: }
                   1294: 
                   1295: #if defined(USE_DLPI_SEND)
                   1296: int can_unicast_without_arp (ip)
                   1297:        struct interface_info *ip;
                   1298: {
                   1299:        return 1;
                   1300: }
                   1301: 
                   1302: int can_receive_unicast_unconfigured (ip)
                   1303:        struct interface_info *ip;
                   1304: {
                   1305:        return 1;
                   1306: }
                   1307: 
                   1308: int supports_multiple_interfaces (ip)
                   1309:        struct interface_info *ip;
                   1310: {
                   1311:        return 1;
                   1312: }
                   1313: 
                   1314: void maybe_setup_fallback ()
                   1315: {
                   1316:        isc_result_t status;
                   1317:        struct interface_info *fbi = (struct interface_info *)0;
                   1318:        if (setup_fallback (&fbi, MDL)) {
                   1319:                if_register_fallback (fbi);
                   1320:                status = omapi_register_io_object ((omapi_object_t *)fbi,
                   1321:                                                   if_readsocket, 0,
                   1322:                                                   fallback_discard, 0, 0);
                   1323:                if (status != ISC_R_SUCCESS)
                   1324:                        log_fatal ("Can't register I/O handle for %s: %s",
                   1325:                                   fbi -> name, isc_result_totext (status));
                   1326:                interface_dereference (&fbi, MDL);
                   1327:        }
                   1328: }
                   1329: #endif /* USE_DLPI_SEND */
                   1330: 
                   1331: void 
                   1332: get_hw_addr(const char *name, struct hardware *hw) {
                   1333:        int sock, unit;
                   1334:        long buf[DLPI_MAXDLBUF];
                   1335:         union DL_primitives *dlp;
                   1336: 
                   1337:         dlp = (union DL_primitives *)buf;
                   1338: 
                   1339:        /* 
                   1340:         * Open a DLPI device.
                   1341:         */
                   1342:        sock = dlpiopen(name);
                   1343:        if (sock < 0) {
                   1344:                log_fatal("Can't open DLPI device for %s: %m", name);
                   1345:        }
                   1346: 
                   1347:        /*
                   1348:         * Submit a DL_INFO_REQ request, to find the dl_mac_type and 
                   1349:          * dl_provider_style
                   1350:         */
                   1351:        if (dlpiinforeq(sock) < 0) {
                   1352:            log_fatal("Can't request DLPI MAC type for %s: %m", name);
                   1353:        }
                   1354:        if (dlpiinfoack(sock, (char *)buf) < 0) {
                   1355:            log_fatal("Can't get DLPI MAC type for %s: %m", name);
                   1356:        }
                   1357:        switch (dlp->info_ack.dl_mac_type) {
                   1358:                case DL_CSMACD: /* IEEE 802.3 */
                   1359:                case DL_ETHER:
                   1360:                        hw->hbuf[0] = HTYPE_ETHER;
                   1361:                        break;
                   1362:                case DL_TPR:
                   1363:                        hw->hbuf[0] = HTYPE_IEEE802;
                   1364:                        break;
                   1365:                case DL_FDDI:
                   1366:                        hw->hbuf[0] = HTYPE_FDDI;
                   1367:                        break;
                   1368:                default:
                   1369:                        log_fatal("%s: unsupported DLPI MAC type %lu", name,
                   1370:                                  (unsigned long)dlp->info_ack.dl_mac_type);
                   1371:        }
                   1372: 
                   1373:        if (dlp->info_ack.dl_provider_style == DL_STYLE2) {
                   1374:                /*
                   1375:                 * Attach to the device.  If this fails, the device
                   1376:                 * does not exist.
                   1377:                 */
                   1378:                unit = dlpiunit((char *)name);
                   1379: 
                   1380:                if (dlpiattachreq(sock, unit) < 0 ||
                   1381:                    dlpiokack(sock, (char *)buf) < 0) {
                   1382:                        log_fatal("Can't attach DLPI device for %s: %m",
                   1383:                                  name);
                   1384:                }
                   1385:        }
                   1386: 
                   1387:        /*
                   1388:         * Submit a DL_PHYS_ADDR_REQ request, to find
                   1389:         * the hardware address.
                   1390:         */
                   1391:        if (dlpiphysaddrreq(sock, DL_CURR_PHYS_ADDR) < 0) {
                   1392:                log_fatal("Can't request DLPI hardware address for %s: %m",
                   1393:                          name);
                   1394:        }
                   1395:        if (dlpiphysaddrack(sock, (char *)buf) < 0) {
                   1396:                log_fatal("Can't get DLPI hardware address for %s: %m",
                   1397:                          name);
                   1398:        }
                   1399:        if (dlp->physaddr_ack.dl_addr_length < sizeof(hw->hbuf)) {
                   1400:                memcpy(hw->hbuf+1, 
                   1401:                       (char *)buf + dlp->physaddr_ack.dl_addr_offset,
                   1402:                       dlp->physaddr_ack.dl_addr_length);
                   1403:                hw->hlen = dlp->physaddr_ack.dl_addr_length + 1;
                   1404:        } else {
                   1405:                memcpy(hw->hbuf+1, 
                   1406:                       (char *)buf + dlp->physaddr_ack.dl_addr_offset,
                   1407:                       sizeof(hw->hbuf)-1);
                   1408:                hw->hlen = sizeof(hw->hbuf);
                   1409:        }
                   1410: 
                   1411:        close(sock);
                   1412: }
                   1413: #endif /* USE_DLPI_SEND || USE_DLPI_RECEIVE || USE_DLPI_HWADDR */

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