Annotation of embedaddon/libnet/src/libnet_link_dlpi.c, revision 1.1.1.3

1.1       misho       1: /*
                      2:  *  $Id: libnet_link_dlpi.c,v 1.8 2004/01/28 19:45:00 mike Exp $
                      3:  *
                      4:  *  libnet
                      5:  *  libnet_dlpi.c - dlpi routines
                      6:  *
                      7:  *  Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com>
                      8:  *  All rights reserved.
                      9:  *
                     10:  * Copyright (c) 1993, 1994, 1995, 1996, 1997
                     11:  *     The Regents of the University of California.  All rights reserved.
                     12:  *
                     13:  * Redistribution and use in source and binary forms, with or without
                     14:  * modification, are permitted provided that: (1) source code distributions
                     15:  * retain the above copyright notice and this paragraph in its entirety, (2)
                     16:  * distributions including binary code include the above copyright notice and
                     17:  * this paragraph in its entirety in the documentation or other materials
                     18:  * provided with the distribution, and (3) all advertising materials mentioning
                     19:  * features or use of this software display the following acknowledgement:
                     20:  * ``This product includes software developed by the University of California,
                     21:  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
                     22:  * the University nor the names of its contributors may be used to endorse
                     23:  * or promote products derived from this software without specific prior
                     24:  * written permission.
                     25:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     26:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     27:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     28:  *
                     29:  * This code contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk),
                     30:  * University College London.
                     31:  */
                     32: 
                     33: 
1.1.1.3 ! misho      34: #include "common.h"
        !            35: 
1.1       misho      36: #include <sys/types.h>
                     37: #include <sys/time.h>
                     38: #ifdef HAVE_SYS_BUFMOD_H
                     39: #include <sys/bufmod.h>
                     40: #endif
                     41: #include <sys/dlpi.h>
                     42: #ifdef HAVE_HPUX9
                     43: #include <sys/socket.h>
                     44: #endif
                     45: #ifdef DL_HP_PPA_ACK_OBS
                     46: #include <sys/stat.h>
                     47: #endif
                     48: #include <sys/stream.h>
                     49: #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
                     50: #include <sys/systeminfo.h>
                     51: #endif
                     52: 
                     53: #ifdef HAVE_SYS_DLPI_EXT_H
                     54: #include <sys/dlpi_ext.h>
                     55: #endif
                     56: 
                     57: #ifdef HAVE_HPUX9
                     58: #include <net/if.h>
                     59: #endif
                     60: 
                     61: #include <ctype.h>
                     62: #ifdef HAVE_HPUX9
                     63: #include <nlist.h>
                     64: #include <dlpi_ext.h>
                     65: #endif
                     66: #include <errno.h>
                     67: #include <fcntl.h>
                     68: #include <memory.h>
                     69: #include <stdio.h>
                     70: #include <stdlib.h>
                     71: #include <string.h>
                     72: #include <stropts.h>
                     73: #include <unistd.h>
                     74: 
                     75: #include "../include/libnet.h"
                     76: #include "../include/bpf.h"
                     77: 
                     78: #include "../include/gnuc.h"
                     79: #ifdef HAVE_OS_PROTO_H
                     80: #include "../include/os-proto.h"
                     81: #endif
                     82: 
                     83: #ifndef DLPI_DEV_PREFIX
                     84: #define DLPI_DEV_PREFIX "/dev"
                     85: #endif
                     86: 
                     87: #define        MAXDLBUF 8192
                     88: 
                     89: /* Forwards */
                     90: static int dlattachreq(int, bpf_u_int32, int8_t *);
                     91: static int dlbindack(int, int8_t *, int8_t *);
                     92: static int dlbindreq(int, bpf_u_int32, int8_t *);
                     93: static int dlinfoack(int, int8_t *, int8_t *);
                     94: static int dlinforeq(int, int8_t *);
                     95: static int dlokack(int, const int8_t *, int8_t *, int8_t *);
                     96: static int recv_ack(int, int, const int8_t *, int8_t *, int8_t *);
                     97: static int send_request(int, int8_t *, int, int8_t *, int8_t *, int);
                     98: #ifdef HAVE_SYS_BUFMOD_H
                     99: static int strioctl(int, int, int, int8_t *);
                    100: #endif
                    101: #ifdef HAVE_HPUX9
1.1.1.2   misho     102: static int dlpi_kread(int, off_t, void *, uint, int8_t *);
1.1       misho     103: #endif
                    104: #ifdef HAVE_DEV_DLPI
                    105: static int get_dlpi_ppa(int, const int8_t *, int, int8_t *);
                    106: #endif
                    107: 
                    108: /* XXX Needed by HP-UX (at least) */
                    109: static bpf_u_int32 ctlbuf[MAXDLBUF];
                    110: 
1.1.1.3 ! misho     111: /* Return a pointer to the last character in 'in' that is not in 's',
        !           112:  * or NULL if no such character exists. */
        !           113: static char *find_last_not_of(char *in, const char *s)
        !           114: {
        !           115:   char* cur;
        !           116:   cur = in + strlen(in);
        !           117:   for(; cur != in; cur--) {
        !           118:     if (!strchr(s, *cur)) {
        !           119:       break;
        !           120:     }
        !           121:   }
        !           122:   return cur == in ? NULL : cur;
        !           123: }
        !           124: 
        !           125: /* Split device into device type and unit number.
        !           126:  * Return >0 on success. */
        !           127: static int
        !           128: dlpi_unit(const char *dev, int *namelen, int *unit)
        !           129: {
        !           130:     char *p;
        !           131:     char *eos;
        !           132:     if (!*dev) {
        !           133:         return 0;
        !           134:     }
        !           135:     p = find_last_not_of(dev, "0123456789");
        !           136:     if (!p) {
        !           137:         return 0;
        !           138:     }
        !           139:     p++;
        !           140:     if (!*p) {
        !           141:         return 0;
        !           142:     }
        !           143:     *unit = strtol(p, NULL, 10);
        !           144:     *namelen = p - dev;
        !           145:     return 1;
        !           146: }
        !           147: 
        !           148: /* Sometimes the network device is at /dev/<ifname>, and sometimes at
        !           149:  * /dev/net/<ifname>. Sometimes both. Sometimes with unit number, sometimes
        !           150:  * without.
        !           151:  * This function tries to find the device, and won't be stopped just because
        !           152:  * it tried to open a directory. (e.g. interface net0 would try to open
        !           153:  * /dev/net).
        !           154:  */
        !           155: static int
        !           156: try_open_dev(libnet_t *l, const char *dev, int unit)
        !           157: {
        !           158:     const char *prefixes[] = {
        !           159:         DLPI_DEV_PREFIX,
        !           160:         "/dev",
        !           161:         "/dev/net",
        !           162:         "",
        !           163:         NULL
        !           164:     };
        !           165:     int ret;
        !           166:     char fullpath[MAXPATHLEN];
        !           167:     int cur_prefix;
        !           168: 
        !           169:     for (cur_prefix = 0; prefixes[cur_prefix]; cur_prefix++) {
        !           170:         snprintf(fullpath, sizeof(fullpath),
        !           171:                  "%s/%s", prefixes[cur_prefix], dev);
        !           172:         if (0 <= (ret = open(fullpath, O_RDWR))) {
        !           173:             return ret;
        !           174:         }
        !           175:         if (errno != ENOENT && errno != EISDIR) {
        !           176:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): open(): %s: %s",
        !           177:                      __func__, fullpath, strerror(errno));
        !           178:             return -1;
        !           179:         }
        !           180:         snprintf(fullpath, sizeof(fullpath),
        !           181:                  "%s/%s%d", prefixes[cur_prefix], dev, unit);
        !           182:         if (0 <= (ret = open(fullpath, O_RDWR))) {
        !           183:             return ret;
        !           184:         }
        !           185:         if (errno != ENOENT && errno != EISDIR) {
        !           186:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): open(): %s: %s",
        !           187:                      __func__, fullpath, strerror(errno));
        !           188:             return -1;
        !           189:         }
        !           190:     }
        !           191:     return -1;
        !           192: }
1.1       misho     193: 
                    194: int
                    195: libnet_open_link(libnet_t *l)
                    196: {
                    197:     register int8_t *cp;
                    198:     int8_t *eos;
1.1.1.3 ! misho     199:     int ppa;
1.1       misho     200:     register dl_info_ack_t *infop;
                    201:     bpf_u_int32 buf[MAXDLBUF];
1.1.1.3 ! misho     202:     int namelen;
        !           203:     int8_t dname[MAXPATHLEN];
1.1       misho     204: 
                    205:     if (l == NULL)
                    206:     { 
                    207:         return (-1);
                    208:     } 
                    209: 
1.1.1.3 ! misho     210:     memset(&dname, 0, sizeof(dname));
        !           211: 
1.1       misho     212:     /*
                    213:      *  Determine device and ppa
                    214:      */
1.1.1.3 ! misho     215:     if (!dlpi_unit(l->device, &namelen, &ppa)) {
1.1       misho     216:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.3 ! misho     217:                 "%s(): %s has bad device type or unit number",
        !           218:                 __func__, l->device);
1.1       misho     219:         goto bad;
                    220:     }
1.1.1.3 ! misho     221:     strncpy(dname, l->device, namelen);
1.1       misho     222: 
1.1.1.3 ! misho     223: #ifdef HAVE_DEV_DLPI
1.1       misho     224:     if (*(l->device) == '/')
                    225:     {
                    226:         strncpy(dname, l->device, sizeof(dname) - 1);
                    227:         dname[sizeof(dname) - 1] = '\0';
                    228:     }
                    229:     else
                    230:     {
1.1.1.3 ! misho     231:         snprintf(dname, sizeof(dname), "%s/%s", DLPI_DEV_PREFIX, l->device);
1.1       misho     232:     }
1.1.1.3 ! misho     233: 
1.1       misho     234:     /*
                    235:      *  Map network device to /dev/dlpi unit
                    236:      */
                    237:     cp = "/dev/dlpi";
                    238: 
                    239:     l->fd = open(cp, O_RDWR);
                    240:     if (l->fd == -1)
                    241:     {
                    242:         goto bad;
                    243:     }
                    244: 
                    245:     /*
                    246:      *  Map network interface to /dev/dlpi unit
                    247:      */
                    248:     ppa = get_dlpi_ppa(l->fd, dname, ppa, l->err_buf);
                    249:     if (ppa < 0)
                    250:     {
                    251:         goto bad;
                    252:     }
                    253: #else
                    254:     /*
                    255:      *  Try device without unit number
                    256:      */
1.1.1.3 ! misho     257:     l->fd = try_open_dev(l, dname, ppa);
        !           258:     if (l->fd == -1) {
        !           259:         goto bad;
1.1       misho     260:     }
                    261: #endif
                    262:     /*
                    263:      *  Attach if "style 2" provider
                    264:      */
                    265:     if (dlinforeq(l->fd, l->err_buf) < 0 ||
                    266:             dlinfoack(l->fd, (int8_t *)buf, l->err_buf) < 0)
                    267:     {
                    268:         goto bad;
                    269:     }
                    270:     infop = &((union DL_primitives *)buf)->info_ack;
                    271:     if (infop->dl_provider_style == DL_STYLE2 &&
                    272:             (dlattachreq(l->fd, ppa, l->err_buf)
                    273:             < 0 || dlokack(l->fd, "attach", (int8_t *)buf, l->err_buf) < 0))
                    274:     {
                    275:         goto bad;
                    276:     }
                    277: 
                    278:     /*
                    279:      *  Bind HP-UX 9 and HP-UX 10.20
                    280:      */
                    281: #if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20) || defined(HAVE_HPUX11) || defined(HAVE_SOLARIS)
                    282:     if (dlbindreq(l->fd, 0, l->err_buf) < 0 ||
                    283:             dlbindack(l->fd, (int8_t *)buf, l->err_buf) < 0)
                    284:     {
                    285:         goto bad;
                    286:     }
                    287: #endif
                    288: 
                    289:     /*
                    290:      *  Determine link type
                    291:      */
                    292:     if (dlinforeq(l->fd, l->err_buf) < 0 ||
                    293:             dlinfoack(l->fd, (int8_t *)buf, l->err_buf) < 0)
                    294:     {
                    295:         goto bad;
                    296:     }
                    297: 
                    298:     infop = &((union DL_primitives *)buf)->info_ack;
                    299:     switch (infop->dl_mac_type)
                    300:     {
                    301:         case DL_CSMACD:
                    302:         case DL_ETHER:
                    303:             l->link_type    = DLT_EN10MB;
                    304:             l->link_offset  = 0xe;
                    305:             break;
                    306:         case DL_FDDI:
                    307:             l->link_type    = DLT_FDDI;
                    308:             l->link_offset  = 0x15;
                    309:             break;
                    310:         case DL_TPR:
                    311:             l->link_type    = DLT_PRONET;
                    312:             l->link_offset  = 0x16;
                    313:             break;
                    314:         default:
1.1.1.3 ! misho     315:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
        !           316:                      "%s(): unknown mac type 0x%lu", __func__,
1.1.1.2   misho     317:                     (uint32_t) infop->dl_mac_type);
1.1       misho     318:             goto bad;
                    319:     }
                    320: 
                    321: #ifdef DLIOCRAW
                    322:     /*
                    323:      *  This is a non standard SunOS hack to get the ethernet header.
                    324:      */
                    325:     if (strioctl(l->fd, DLIOCRAW, 0, NULL) < 0)
                    326:     {
1.1.1.3 ! misho     327:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
        !           328:                  "%s(): DLIOCRAW: %s", __func__, strerror(errno));
1.1       misho     329:         goto bad;
                    330:     }
                    331: #endif
                    332: 
                    333:     return (1);
                    334: bad:
                    335:     if (l->fd > 0)
                    336:     {
                    337:         close(l->fd);      /* this can fail ok */
                    338:     }
                    339:     return (-1);
                    340: }
                    341: 
                    342: 
                    343: static int
                    344: send_request(int fd, int8_t *ptr, int len, int8_t *what, int8_t *ebuf,
                    345: int flags)
                    346: {
                    347:     struct strbuf ctl;
                    348: 
                    349:     ctl.maxlen = 0;
                    350:     ctl.len = len;
                    351:     ctl.buf = ptr;
                    352: 
                    353:     if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0)
                    354:     {
1.1.1.3 ! misho     355:         snprintf(ebuf, LIBNET_ERRBUF_SIZE,
        !           356:                  "%s(): putmsg \"%s\": %s", __func__, what,
1.1       misho     357:                 strerror(errno));
                    358:         return (-1);
                    359:     }
                    360:     return (0);
                    361: }
                    362: 
                    363: static int
                    364: recv_ack(int fd, int size, const int8_t *what, int8_t *bufp, int8_t *ebuf)
                    365: {
                    366:     union DL_primitives *dlp;
                    367:     struct strbuf ctl;
                    368:     int flags;
                    369: 
                    370:     ctl.maxlen = MAXDLBUF;
                    371:     ctl.len = 0;
                    372:     ctl.buf = bufp;
                    373: 
                    374:     flags = 0;
                    375:     if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0)
                    376:     {
1.1.1.3 ! misho     377:         snprintf(ebuf, LIBNET_ERRBUF_SIZE,
        !           378:                  "%s(): %s getmsg: %s", __func__, what, strerror(errno));
1.1       misho     379:         return (-1);
                    380:     }
                    381: 
                    382:     dlp = (union DL_primitives *)ctl.buf;
                    383:     switch (dlp->dl_primitive)
                    384:     {
                    385:         case DL_INFO_ACK:
                    386:         case DL_PHYS_ADDR_ACK:
                    387:         case DL_BIND_ACK:
                    388:         case DL_OK_ACK:
                    389: #ifdef DL_HP_PPA_ACK
                    390:         case DL_HP_PPA_ACK:
                    391: #endif
                    392:         /*
                    393:          *  These are OK
                    394:          */
                    395:         break;
                    396: 
                    397:         case DL_ERROR_ACK:
                    398:             switch (dlp->error_ack.dl_errno)
                    399:             {
                    400:                 case DL_BADPPA:
1.1.1.3 ! misho     401:                     snprintf(ebuf, LIBNET_ERRBUF_SIZE,
        !           402:                              "recv_ack: %s bad ppa (device unit)", what);
1.1       misho     403:                     break;
                    404:                 case DL_SYSERR:
1.1.1.3 ! misho     405:                     snprintf(ebuf, LIBNET_ERRBUF_SIZE,
        !           406:                              "recv_ack: %s: %s",
1.1       misho     407:                         what, strerror(dlp->error_ack.dl_unix_errno));
                    408:                     break;
                    409:                 case DL_UNSUPPORTED:
1.1.1.3 ! misho     410:                     snprintf(ebuf, LIBNET_ERRBUF_SIZE,
1.1       misho     411:                         "recv_ack: %s: Service not supplied by provider", what);
                    412:                     break;
                    413:                 default:
1.1.1.3 ! misho     414:                     snprintf(ebuf, LIBNET_ERRBUF_SIZE,
        !           415:                              "recv_ack: %s error 0x%x", what,
1.1       misho     416:                         (bpf_u_int32)dlp->error_ack.dl_errno);
                    417:                     break;
                    418:             }
                    419:             return (-1);
                    420: 
                    421:         default:
1.1.1.3 ! misho     422:             snprintf(ebuf, LIBNET_ERRBUF_SIZE,
        !           423:                      "recv_ack: %s unexpected primitive ack 0x%x ",
1.1       misho     424:                 what, (bpf_u_int32)dlp->dl_primitive);
                    425:             return (-1);
                    426:     }
                    427: 
                    428:     if (ctl.len < size)
                    429:     {
1.1.1.3 ! misho     430:         snprintf(ebuf, LIBNET_ERRBUF_SIZE,
        !           431:                  "recv_ack: %s ack too small (%d < %d)",
1.1       misho     432:             what, ctl.len, size);
                    433:         return (-1);
                    434:     }
                    435:     return (ctl.len);
                    436: }
                    437: 
                    438: static int
                    439: dlattachreq(int fd, bpf_u_int32 ppa, int8_t *ebuf)
                    440: {
                    441:     dl_attach_req_t req;
                    442: 
                    443:     req.dl_primitive = DL_ATTACH_REQ;
                    444:     req.dl_ppa       = ppa;
                    445: 
                    446:     return (send_request(fd, (int8_t *)&req, sizeof(req), "attach", ebuf, 0));
                    447: }
                    448: 
                    449: static int
                    450: dlbindreq(int fd, bpf_u_int32 sap, int8_t *ebuf)
                    451: {
                    452: 
                    453:     dl_bind_req_t      req;
                    454: 
                    455:     memset((int8_t *)&req, 0, sizeof(req));
                    456:     req.dl_primitive = DL_BIND_REQ;
                    457: #ifdef DL_HP_RAWDLS
                    458:     req.dl_max_conind = 1;  /* XXX magic number */
                    459:     /*
                    460:      *  22 is INSAP as per the HP-UX DLPI Programmer's Guide
                    461:      */
                    462:     req.dl_sap = 22;
                    463:     req.dl_service_mode = DL_HP_RAWDLS;
                    464: #else
                    465:     req.dl_sap = sap;
                    466: #ifdef DL_CLDLS
                    467:     req.dl_service_mode = DL_CLDLS;
                    468: #endif
                    469: #endif
                    470:     return (send_request(fd, (int8_t *)&req, sizeof(req), "bind", ebuf, 0));
                    471: }
                    472: 
                    473: static int
                    474: dlbindack(int fd, int8_t *bufp, int8_t *ebuf)
                    475: {
                    476:     return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf));
                    477: }
                    478: 
                    479: static int
                    480: dlokack(int fd, const int8_t *what, int8_t *bufp, int8_t *ebuf)
                    481: {
                    482:     return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf));
                    483: }
                    484: 
                    485: static int
                    486: dlinforeq(int fd, int8_t *ebuf)
                    487: {
                    488:     dl_info_req_t req;
                    489: 
                    490:     req.dl_primitive = DL_INFO_REQ;
                    491: 
                    492:     return (send_request(fd, (int8_t *)&req, sizeof(req), "info", ebuf, 
                    493:             RS_HIPRI));
                    494: }
                    495: 
                    496: static int
                    497: dlinfoack(int fd, int8_t *bufp, int8_t *ebuf)
                    498: {
                    499:     return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf));
                    500: }
                    501: 
                    502: 
                    503: #ifdef HAVE_SYS_BUFMOD_H
                    504: static int
                    505: strioctl(int fd, int cmd, int len, int8_t *dp)
                    506: {
                    507:     struct strioctl str;
                    508:     int rc;
                    509: 
                    510:     str.ic_cmd    = cmd;
                    511:     str.ic_timout = -1;
                    512:     str.ic_len    = len;
                    513:     str.ic_dp     = dp;
                    514:     
                    515:     rc = ioctl(fd, I_STR, &str);
                    516:     if (rc < 0)
                    517:     {
                    518:         return (rc);
                    519:     }
                    520:     else
                    521:     {
                    522:         return (str.ic_len);
                    523:     }
                    524: }
                    525: #endif
                    526: 
                    527: 
                    528: #if (defined(DL_HP_PPA_ACK_OBS) && !defined(HAVE_HPUX11))
                    529: /*
                    530:  * Under HP-UX 10, we can ask for the ppa
                    531:  */
                    532: static int
                    533: get_dlpi_ppa(register int fd, register const int8_t *device, register int unit,
                    534: register int8_t *ebuf)
                    535: {
                    536:     register dl_hp_ppa_ack_t *ap;
                    537:     register dl_hp_ppa_info_t *ip;
                    538:     register int i;
1.1.1.2   misho     539:     register uint32_t majdev;
1.1       misho     540:     dl_hp_ppa_req_t    req;
                    541:     struct stat statbuf;
                    542:     bpf_u_int32 buf[MAXDLBUF];
                    543: 
                    544:     if (stat(device, &statbuf) < 0)
                    545:     {
1.1.1.3 ! misho     546:         snprintf(ebuf, LIBNET_ERRBUF_SIZE,
        !           547:                  "stat: %s: %s", device, strerror(errno));
1.1       misho     548:         return (-1);
                    549:     }
                    550:     majdev = major(statbuf.st_rdev);
                    551: 
                    552:     memset((int8_t *)&req, 0, sizeof(req));
                    553:     req.dl_primitive = DL_HP_PPA_REQ;
                    554: 
                    555:     memset((int8_t *)buf, 0, sizeof(buf));
                    556:     if (send_request(fd, (int8_t *)&req, sizeof(req), "hpppa", ebuf, 0) < 0 ||
                    557:         recv_ack(fd, DL_HP_PPA_ACK_SIZE, "hpppa", (int8_t *)buf, ebuf) < 0)
                    558:     {
                    559:         return (-1);
                    560:     }
                    561: 
                    562:     ap = (dl_hp_ppa_ack_t *)buf;
1.1.1.2   misho     563:     ip = (dl_hp_ppa_info_t *)((uint8_t *)ap + ap->dl_offset);
1.1       misho     564: 
                    565:     for (i = 0; i < ap->dl_count; i++)
                    566:     {
                    567:         if (ip->dl_mjr_num == majdev && ip->dl_instance_num == unit)
                    568:         break;
                    569: 
1.1.1.2   misho     570:         ip = (dl_hp_ppa_info_t *)((uint8_t *)ip + ip->dl_next_offset);
1.1       misho     571:     }
                    572: 
                    573:     if (i == ap->dl_count)
                    574:     {
1.1.1.3 ! misho     575:         snprintf(ebuf, LIBNET_ERRBUF_SIZE,
        !           576:                  "can't find PPA for %s", device);
1.1       misho     577:         return (-1);
                    578:     }
                    579: 
                    580:     if (ip->dl_hdw_state == HDW_DEAD)
                    581:     {
1.1.1.3 ! misho     582:         snprintf(ebuf, LIBNET_ERRBUF_SIZE,
        !           583:                  "%s: hardware state: DOWN", device);
1.1       misho     584:         return (-1);
                    585:     }
                    586:     return ((int)ip->dl_ppa);
                    587: }
                    588: #endif
                    589: 
                    590: #ifdef HAVE_HPUX9
                    591: /*
                    592:  * Under HP-UX 9, there is no good way to determine the ppa.
                    593:  * So punt and read it from /dev/kmem.
                    594:  */
                    595: static struct nlist nl[] =
                    596: {
                    597: #define NL_IFNET 0
                    598:     { "ifnet" },
                    599:     { "" }
                    600: };
                    601: 
                    602: static int8_t path_vmunix[] = "/hp-ux";
                    603: 
                    604: /*
                    605:  *  Determine ppa number that specifies ifname
                    606:  */
                    607: static int
                    608: get_dlpi_ppa(register int fd, register const int8_t *ifname, register int unit,
                    609:     register int8_t *ebuf)
                    610: {
                    611:     register const int8_t *cp;
                    612:     register int kd;
                    613:     void *addr;
                    614:     struct ifnet ifnet;
                    615:     int8_t if_name[sizeof(ifnet.if_name)], tifname[32];
                    616: 
                    617:     cp = strrchr(ifname, '/');
                    618:     if (cp != NULL)
                    619:     {
                    620:         ifname = cp + 1;
                    621:     }
                    622:     if (nlist(path_vmunix, &nl) < 0)
                    623:     {
1.1.1.3 ! misho     624:         snprintf(ebuf, LIBNET_ERRBUF_SIZE,
        !           625:                  "nlist %s failed", path_vmunix);
1.1       misho     626:         return (-1);
                    627:     }
                    628: 
                    629:     if (nl[NL_IFNET].n_value == 0)
                    630:     {
1.1.1.3 ! misho     631:         snprintf(ebuf, LIBNET_ERRBUF_SIZE,
        !           632:                  "could't find %s kernel symbol", nl[NL_IFNET].n_name);
1.1       misho     633:         return (-1);
                    634:     }
                    635: 
                    636:     kd = open("/dev/kmem", O_RDONLY);
                    637:     if (kd < 0)
                    638:     {
1.1.1.3 ! misho     639:         snprintf(ebuf, LIBNET_ERRBUF_SIZE,
        !           640:                  "kmem open: %s", strerror(errno));
1.1       misho     641:         return (-1);
                    642:     }
                    643: 
                    644:     if (dlpi_kread(kd, nl[NL_IFNET].n_value, &addr, sizeof(addr), ebuf) < 0)
                    645:     {
                    646:         close(kd);
                    647:         return (-1);
                    648:     }
                    649:     for (; addr != NULL; addr = ifnet.if_next)
                    650:     {
                    651:         if (dlpi_kread(kd, (off_t)addr, &ifnet, sizeof(ifnet), ebuf) < 0 ||
                    652:             dlpi_kread(kd, (off_t)ifnet.if_name,
                    653:             if_name, sizeof(if_name), ebuf) < 0)
                    654:             {
                    655:                 close(kd);
                    656:                 return (-1);
                    657:             }
1.1.1.3 ! misho     658:             snprintf(tifname, sizeof(tifname), "%.*s%d",
1.1       misho     659:                 (int)sizeof(if_name), if_name, ifnet.if_unit);
                    660:             if (strcmp(tifname, ifname) == 0)
                    661:             {
                    662:                 return (ifnet.if_index);
                    663:             }
                    664:     }
                    665: 
1.1.1.3 ! misho     666:     snprintf(ebuf, LIBNET_ERRBUF_SIZE,
        !           667:              "Can't find %s", ifname);
1.1       misho     668:     return (-1);
                    669: }
                    670: 
                    671: static int
                    672: dlpi_kread(register int fd, register off_t addr, register void *buf,
1.1.1.2   misho     673: register uint len, register int8_t *ebuf)
1.1       misho     674: {
                    675:     register int cc;
                    676: 
                    677:     if (lseek(fd, addr, SEEK_SET) < 0)
                    678:     {
1.1.1.3 ! misho     679:         snprintf(ebuf, LIBNET_ERRBUF_SIZE,
        !           680:                  "lseek: %s", strerror(errno));
1.1       misho     681:         return (-1);
                    682:     }
                    683:     cc = read(fd, buf, len);
                    684:     if (cc < 0)
                    685:     {
1.1.1.3 ! misho     686:         snprintf(ebuf, LIBNET_ERRBUF_SIZE,
        !           687:                  "read: %s", strerror(errno));
1.1       misho     688:         return (-1);
                    689:     }
                    690:     else if (cc != len)
                    691:     {
1.1.1.3 ! misho     692:         snprintf(ebuf, LIBNET_ERRBUF_SIZE,
        !           693:                  "int16_t read (%d != %d)", cc, len);
1.1       misho     694:         return (-1);
                    695:     }
                    696:     return (cc);
                    697: }
                    698: #endif
                    699: 
                    700: #define ETHERADDRL 6
                    701: struct  EnetHeaderInfo
                    702: {
                    703:     struct libnet_ether_addr   DestEtherAddr;
1.1.1.2   misho     704:     uint16_t EtherFrameType;
1.1       misho     705: };
                    706: 
                    707: 
                    708: int
                    709: libnet_close_link(libnet_t *l)
                    710: {
                    711:     if (close(l->fd) == 0)
                    712:     {
                    713:         return (1);
                    714:     }
                    715:     else
                    716:     {
                    717:         return (-1);
                    718:     }
                    719: }
                    720: 
                    721: #ifdef HAVE_HPUX11
                    722: int 
1.1.1.2   misho     723: libnet_write_link(libnet_t *l, const uint8_t *packet, uint32_t size)   
1.1       misho     724: {                                                             
                    725:     struct strbuf data, ctl;
                    726:     dl_hp_rawdata_req_t *rdata;
                    727:     int c;                     
                    728:                           
                    729:     if (l == NULL)
                    730:     {             
                    731:         return (-1);           
                    732:     }       
                    733:             
                    734:     rdata = (dl_hp_rawdata_req_t *)ctlbuf;
                    735:     rdata->dl_primitive = DL_HP_RAWDATA_REQ; 
                    736: 
                    737:     /* send it */                                  
                    738:     ctl.len = sizeof(dl_hp_rawdata_req_t);                         
                    739:     ctl.maxlen = sizeof(dl_hp_rawdata_req_t);                      
                    740:     ctl.buf = (int8_t *)rdata;
                    741: 
                    742:     data.maxlen = size;
                    743:     data.len    = size;                                
                    744:     data.buf    = packet;  
                    745: 
                    746:     c = putmsg(l->fd, &ctl, &data, 0);
                    747:     if (c == -1)                      
                    748:     {                    
                    749:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.3 ! misho     750:                 "libnet_write_link(): %d bytes written (%s)", c,
1.1       misho     751:                 strerror(errno));
                    752:         return (-1);
                    753:     }
                    754:     else
                    755:     {
                    756:         return (size);
                    757:     }                
                    758: }   
                    759: #else
                    760: int
1.1.1.2   misho     761: libnet_write_link(libnet_t *l, const uint8_t *packet, uint32_t size)
1.1       misho     762: {
                    763:     int c;
                    764:     struct strbuf data;
                    765: 
                    766:     if (l == NULL)
                    767:     { 
                    768:         return (-1);
                    769:     } 
                    770: 
                    771:     data.maxlen = size;
                    772:     data.len    = size;
                    773:     data.buf    = packet;
                    774: 
                    775:     c = putmsg(l->fd, NULL, &data, 0);
                    776:     if (c == -1)
                    777:     {
                    778:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.3 ! misho     779:                 "libnet_write_link: %d bytes written (%s)", c,
1.1       misho     780:                 strerror(errno));
                    781:         return (-1);
                    782:     }
                    783:     else
                    784:     {
                    785:         return (size);
                    786:     }
                    787: }
                    788: #endif
                    789: 
                    790: struct libnet_ether_addr *
                    791: libnet_get_hwaddr(libnet_t *l)
                    792: {
                    793:     union DL_primitives *dlp;
1.1.1.3 ! misho     794:     int8_t *buf;
        !           795:     int8_t *mac;
1.1       misho     796: 
                    797:     if (l == NULL)
                    798:     { 
                    799:         return (NULL);
                    800:     }
                    801: 
1.1.1.3 ! misho     802:     buf = (int8_t *)malloc(2048);
        !           803:     if (buf == NULL)
        !           804:     {
        !           805:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): malloc(): %s",
        !           806:                 __func__, strerror(errno));
        !           807:         return (NULL);
        !           808:     }
        !           809: 
1.1       misho     810:     dlp = (union DL_primitives *)buf;
                    811: 
                    812:     dlp->physaddr_req.dl_primitive = DL_PHYS_ADDR_REQ;
                    813:     dlp->physaddr_req.dl_addr_type = DL_CURR_PHYS_ADDR;
                    814: 
                    815:     if (send_request(l->fd, (int8_t *)dlp, DL_PHYS_ADDR_REQ_SIZE, "physaddr",
                    816:             l->err_buf, 0) < 0)
                    817:     {
1.1.1.3 ! misho     818:         free(buf);
1.1       misho     819:         return (NULL);
                    820:     }
                    821:     if (recv_ack(l->fd, DL_PHYS_ADDR_ACK_SIZE, "physaddr", (int8_t *)dlp,
                    822:             l->err_buf) < 0)
                    823:     {
1.1.1.3 ! misho     824:         free(buf);
1.1       misho     825:         return (NULL);
                    826:     }
                    827: 
1.1.1.3 ! misho     828:     mac = (int8_t *)dlp + dlp->physaddr_ack.dl_addr_offset;
        !           829:     memcpy(l->link_addr.ether_addr_octet, mac, ETHER_ADDR_LEN);
        !           830:     free(buf);
        !           831: 
        !           832:     return (&l->link_addr);
1.1       misho     833: }   
                    834: 
1.1.1.3 ! misho     835: /**
        !           836:  * Local Variables:
        !           837:  *  indent-tabs-mode: nil
        !           838:  *  c-file-style: "stroustrup"
        !           839:  * End:
        !           840:  */

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