File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libnet / src / libnet_link_dlpi.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Sep 27 11:11:38 2023 UTC (8 months, 4 weeks ago) by misho
Branches: libnet, MAIN
CVS tags: v1_2p1, HEAD
Version 1.2p1

    1: /*
    2:  *  $Id: libnet_link_dlpi.c,v 1.1.1.3 2023/09/27 11:11:38 misho 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: 
   34: #include "common.h"
   35: 
   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
  102: static int dlpi_kread(int, off_t, void *, uint, int8_t *);
  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: 
  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: }
  193: 
  194: int
  195: libnet_open_link(libnet_t *l)
  196: {
  197:     register int8_t *cp;
  198:     int8_t *eos;
  199:     int ppa;
  200:     register dl_info_ack_t *infop;
  201:     bpf_u_int32 buf[MAXDLBUF];
  202:     int namelen;
  203:     int8_t dname[MAXPATHLEN];
  204: 
  205:     if (l == NULL)
  206:     { 
  207:         return (-1);
  208:     } 
  209: 
  210:     memset(&dname, 0, sizeof(dname));
  211: 
  212:     /*
  213:      *  Determine device and ppa
  214:      */
  215:     if (!dlpi_unit(l->device, &namelen, &ppa)) {
  216:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  217:                 "%s(): %s has bad device type or unit number",
  218: 		 __func__, l->device);
  219:         goto bad;
  220:     }
  221:     strncpy(dname, l->device, namelen);
  222: 
  223: #ifdef HAVE_DEV_DLPI
  224:     if (*(l->device) == '/')
  225:     {
  226:         strncpy(dname, l->device, sizeof(dname) - 1);
  227:         dname[sizeof(dname) - 1] = '\0';
  228:     }
  229:     else
  230:     {
  231:         snprintf(dname, sizeof(dname), "%s/%s", DLPI_DEV_PREFIX, l->device);
  232:     }
  233: 
  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:      */
  257:     l->fd = try_open_dev(l, dname, ppa);
  258:     if (l->fd == -1) {
  259:         goto bad;
  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:
  315:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  316:                      "%s(): unknown mac type 0x%lu", __func__,
  317:                     (uint32_t) infop->dl_mac_type);
  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:     {
  327:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  328:                  "%s(): DLIOCRAW: %s", __func__, strerror(errno));
  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:     {
  355:         snprintf(ebuf, LIBNET_ERRBUF_SIZE,
  356:                  "%s(): putmsg \"%s\": %s", __func__, what,
  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:     {
  377:         snprintf(ebuf, LIBNET_ERRBUF_SIZE,
  378:                  "%s(): %s getmsg: %s", __func__, what, strerror(errno));
  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:
  401:                     snprintf(ebuf, LIBNET_ERRBUF_SIZE,
  402:                              "recv_ack: %s bad ppa (device unit)", what);
  403:                     break;
  404:                 case DL_SYSERR:
  405:                     snprintf(ebuf, LIBNET_ERRBUF_SIZE,
  406:                              "recv_ack: %s: %s",
  407:                         what, strerror(dlp->error_ack.dl_unix_errno));
  408:                     break;
  409:                 case DL_UNSUPPORTED:
  410:                     snprintf(ebuf, LIBNET_ERRBUF_SIZE,
  411:                         "recv_ack: %s: Service not supplied by provider", what);
  412:                     break;
  413:                 default:
  414:                     snprintf(ebuf, LIBNET_ERRBUF_SIZE,
  415:                              "recv_ack: %s error 0x%x", what,
  416:                         (bpf_u_int32)dlp->error_ack.dl_errno);
  417:                     break;
  418:             }
  419:             return (-1);
  420: 
  421:         default:
  422:             snprintf(ebuf, LIBNET_ERRBUF_SIZE,
  423:                      "recv_ack: %s unexpected primitive ack 0x%x ",
  424:                 what, (bpf_u_int32)dlp->dl_primitive);
  425:             return (-1);
  426:     }
  427: 
  428:     if (ctl.len < size)
  429:     {
  430:         snprintf(ebuf, LIBNET_ERRBUF_SIZE,
  431:                  "recv_ack: %s ack too small (%d < %d)",
  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;
  539:     register uint32_t majdev;
  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:     {
  546:         snprintf(ebuf, LIBNET_ERRBUF_SIZE,
  547:                  "stat: %s: %s", device, strerror(errno));
  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;
  563:     ip = (dl_hp_ppa_info_t *)((uint8_t *)ap + ap->dl_offset);
  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: 
  570:         ip = (dl_hp_ppa_info_t *)((uint8_t *)ip + ip->dl_next_offset);
  571:     }
  572: 
  573:     if (i == ap->dl_count)
  574:     {
  575:         snprintf(ebuf, LIBNET_ERRBUF_SIZE,
  576:                  "can't find PPA for %s", device);
  577:         return (-1);
  578:     }
  579: 
  580:     if (ip->dl_hdw_state == HDW_DEAD)
  581:     {
  582:         snprintf(ebuf, LIBNET_ERRBUF_SIZE,
  583:                  "%s: hardware state: DOWN", device);
  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:     {
  624:         snprintf(ebuf, LIBNET_ERRBUF_SIZE,
  625:                  "nlist %s failed", path_vmunix);
  626:         return (-1);
  627:     }
  628: 
  629:     if (nl[NL_IFNET].n_value == 0)
  630:     {
  631:         snprintf(ebuf, LIBNET_ERRBUF_SIZE,
  632:                  "could't find %s kernel symbol", nl[NL_IFNET].n_name);
  633:         return (-1);
  634:     }
  635: 
  636:     kd = open("/dev/kmem", O_RDONLY);
  637:     if (kd < 0)
  638:     {
  639:         snprintf(ebuf, LIBNET_ERRBUF_SIZE,
  640:                  "kmem open: %s", strerror(errno));
  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:             }
  658:             snprintf(tifname, sizeof(tifname), "%.*s%d",
  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: 
  666:     snprintf(ebuf, LIBNET_ERRBUF_SIZE,
  667:              "Can't find %s", ifname);
  668:     return (-1);
  669: }
  670: 
  671: static int
  672: dlpi_kread(register int fd, register off_t addr, register void *buf,
  673: register uint len, register int8_t *ebuf)
  674: {
  675:     register int cc;
  676: 
  677:     if (lseek(fd, addr, SEEK_SET) < 0)
  678:     {
  679:         snprintf(ebuf, LIBNET_ERRBUF_SIZE,
  680:                  "lseek: %s", strerror(errno));
  681:         return (-1);
  682:     }
  683:     cc = read(fd, buf, len);
  684:     if (cc < 0)
  685:     {
  686:         snprintf(ebuf, LIBNET_ERRBUF_SIZE,
  687:                  "read: %s", strerror(errno));
  688:         return (-1);
  689:     }
  690:     else if (cc != len)
  691:     {
  692:         snprintf(ebuf, LIBNET_ERRBUF_SIZE,
  693:                  "int16_t read (%d != %d)", cc, len);
  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;
  704:     uint16_t EtherFrameType;
  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 
  723: libnet_write_link(libnet_t *l, const uint8_t *packet, uint32_t size)   
  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,
  750:                 "libnet_write_link(): %d bytes written (%s)", c,
  751:                 strerror(errno));
  752:         return (-1);
  753:     }
  754:     else
  755:     {
  756:         return (size);
  757:     }                
  758: }   
  759: #else
  760: int
  761: libnet_write_link(libnet_t *l, const uint8_t *packet, uint32_t size)
  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,
  779:                 "libnet_write_link: %d bytes written (%s)", c,
  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;
  794:     int8_t *buf;
  795:     int8_t *mac;
  796: 
  797:     if (l == NULL)
  798:     { 
  799:         return (NULL);
  800:     }
  801: 
  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: 
  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:     {
  818:         free(buf);
  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:     {
  824:         free(buf);
  825:         return (NULL);
  826:     }
  827: 
  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);
  833: }   
  834: 
  835: /**
  836:  * Local Variables:
  837:  *  indent-tabs-mode: nil
  838:  *  c-file-style: "stroustrup"
  839:  * End:
  840:  */

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