File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libnet / src / libnet_link_dlpi.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:14:23 2012 UTC (12 years, 4 months ago) by misho
Branches: libnet, MAIN
CVS tags: v1_1_2_1, HEAD
libnet

    1: /*
    2:  *  $Id: libnet_link_dlpi.c,v 1.1.1.1 2012/02/21 22:14:23 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: #if (HAVE_CONFIG_H)
   35: #include "../include/config.h"
   36: #endif
   37: #include <sys/types.h>
   38: #include <sys/time.h>
   39: #ifdef HAVE_SYS_BUFMOD_H
   40: #include <sys/bufmod.h>
   41: #endif
   42: #include <sys/dlpi.h>
   43: #ifdef HAVE_HPUX9
   44: #include <sys/socket.h>
   45: #endif
   46: #ifdef DL_HP_PPA_ACK_OBS
   47: #include <sys/stat.h>
   48: #endif
   49: #include <sys/stream.h>
   50: #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
   51: #include <sys/systeminfo.h>
   52: #endif
   53: 
   54: #ifdef HAVE_SYS_DLPI_EXT_H
   55: #include <sys/dlpi_ext.h>
   56: #endif
   57: 
   58: #ifdef HAVE_HPUX9
   59: #include <net/if.h>
   60: #endif
   61: 
   62: #include <ctype.h>
   63: #ifdef HAVE_HPUX9
   64: #include <nlist.h>
   65: #include <dlpi_ext.h>
   66: #endif
   67: #include <errno.h>
   68: #include <fcntl.h>
   69: #include <memory.h>
   70: #include <stdio.h>
   71: #include <stdlib.h>
   72: #include <string.h>
   73: #include <stropts.h>
   74: #include <unistd.h>
   75: 
   76: #include "../include/libnet.h"
   77: #include "../include/bpf.h"
   78: 
   79: #include "../include/gnuc.h"
   80: #ifdef HAVE_OS_PROTO_H
   81: #include "../include/os-proto.h"
   82: #endif
   83: 
   84: #ifndef DLPI_DEV_PREFIX
   85: #define DLPI_DEV_PREFIX "/dev"
   86: #endif
   87: 
   88: #define	MAXDLBUF 8192
   89: 
   90: /* Forwards */
   91: static int dlattachreq(int, bpf_u_int32, int8_t *);
   92: static int dlbindack(int, int8_t *, int8_t *);
   93: static int dlbindreq(int, bpf_u_int32, int8_t *);
   94: static int dlinfoack(int, int8_t *, int8_t *);
   95: static int dlinforeq(int, int8_t *);
   96: static int dlokack(int, const int8_t *, int8_t *, int8_t *);
   97: static int recv_ack(int, int, const int8_t *, int8_t *, int8_t *);
   98: static int send_request(int, int8_t *, int, int8_t *, int8_t *, int);
   99: #ifdef HAVE_SYS_BUFMOD_H
  100: static int strioctl(int, int, int, int8_t *);
  101: #endif
  102: #ifdef HAVE_HPUX9
  103: static int dlpi_kread(int, off_t, void *, u_int, int8_t *);
  104: #endif
  105: #ifdef HAVE_DEV_DLPI
  106: static int get_dlpi_ppa(int, const int8_t *, int, int8_t *);
  107: #endif
  108: 
  109: /* XXX Needed by HP-UX (at least) */
  110: static bpf_u_int32 ctlbuf[MAXDLBUF];
  111: 
  112: 
  113: int
  114: libnet_open_link(libnet_t *l)
  115: {
  116:     register int8_t *cp;
  117:     int8_t *eos;
  118:     register int ppa;
  119:     register dl_info_ack_t *infop;
  120:     bpf_u_int32 buf[MAXDLBUF];
  121:     int8_t dname[100];
  122: #ifndef HAVE_DEV_DLPI
  123:     int8_t dname2[100];
  124: #endif
  125: 
  126:     if (l == NULL)
  127:     { 
  128:         return (-1);
  129:     } 
  130: 
  131:     /*
  132:      *  Determine device and ppa
  133:      */
  134:     cp = strpbrk(l->device, "0123456789");
  135:     if (cp == NULL)
  136:     {
  137:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  138:                 "%s(): %s is missing unit number\n", __func__, l->device);
  139:         goto bad;
  140:     }
  141:     ppa = strtol(cp, &eos, 10);
  142:     if (*eos != '\0')
  143:     {
  144:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  145:                 "%s(): %s bad unit number\n", __func__, l->device);
  146:         goto bad;
  147:     }
  148: 
  149:     if (*(l->device) == '/')
  150:     {
  151:         memset(&dname, 0, sizeof(dname));
  152:         strncpy(dname, l->device, sizeof(dname) - 1);
  153:         dname[sizeof(dname) - 1] = '\0';
  154:     }
  155:     else
  156:     {
  157:         sprintf(dname, "%s/%s", DLPI_DEV_PREFIX, l->device);
  158:     }
  159: #ifdef HAVE_DEV_DLPI
  160:     /*
  161:      *  Map network device to /dev/dlpi unit
  162:      */
  163:     cp = "/dev/dlpi";
  164: 
  165:     l->fd = open(cp, O_RDWR);
  166:     if (l->fd == -1)
  167:     {
  168:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): open(): %s: %s\n",
  169:                 __func__, cp, strerror(errno));
  170:         goto bad;
  171:     }
  172: 
  173:     /*
  174:      *  Map network interface to /dev/dlpi unit
  175:      */
  176:     ppa = get_dlpi_ppa(l->fd, dname, ppa, l->err_buf);
  177:     if (ppa < 0)
  178:     {
  179:         goto bad;
  180:     }
  181: #else
  182:     /*
  183:      *  Try device without unit number
  184:      */
  185:     strcpy(dname2, dname);
  186:     cp = strchr(dname, *cp);
  187:     *cp = '\0';
  188: 
  189:     l->fd = open(dname, O_RDWR);
  190:     if (l->fd == -1)
  191:     {
  192:         if (errno != ENOENT)
  193:         {
  194:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): open(): %s: %s\n",
  195:                     __func__, dname, strerror(errno));
  196:             goto bad;
  197:         }
  198: 
  199:         /*
  200:          *  Try again with unit number
  201:          */
  202:         l->fd = open(dname2, O_RDWR);
  203:         if (l->fd == -1)
  204:         {
  205:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): open(): %s: %s\n",
  206:                     __func__, dname2, strerror(errno));
  207:             goto bad;
  208:         }
  209: 
  210:         cp = dname2;
  211:         while (*cp && !isdigit((int)*cp))
  212:         {
  213:             cp++;
  214:         }
  215:         if (*cp)
  216:         {
  217:             ppa = atoi(cp);
  218:         }
  219:         else
  220:         /*
  221:          *  XXX Assume unit zero
  222:          */
  223:         ppa = 0;
  224:     }
  225: #endif
  226:     /*
  227:      *  Attach if "style 2" provider
  228:      */
  229:     if (dlinforeq(l->fd, l->err_buf) < 0 ||
  230:             dlinfoack(l->fd, (int8_t *)buf, l->err_buf) < 0)
  231:     {
  232:         goto bad;
  233:     }
  234:     infop = &((union DL_primitives *)buf)->info_ack;
  235:     if (infop->dl_provider_style == DL_STYLE2 &&
  236:             (dlattachreq(l->fd, ppa, l->err_buf)
  237:             < 0 || dlokack(l->fd, "attach", (int8_t *)buf, l->err_buf) < 0))
  238:     {
  239:         goto bad;
  240:     }
  241: 
  242:     /*
  243:      *  Bind HP-UX 9 and HP-UX 10.20
  244:      */
  245: #if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20) || defined(HAVE_HPUX11) || defined(HAVE_SOLARIS)
  246:     if (dlbindreq(l->fd, 0, l->err_buf) < 0 ||
  247:             dlbindack(l->fd, (int8_t *)buf, l->err_buf) < 0)
  248:     {
  249:         goto bad;
  250:     }
  251: #endif
  252: 
  253:     /*
  254:      *  Determine link type
  255:      */
  256:     if (dlinforeq(l->fd, l->err_buf) < 0 ||
  257:             dlinfoack(l->fd, (int8_t *)buf, l->err_buf) < 0)
  258:     {
  259:         goto bad;
  260:     }
  261: 
  262:     infop = &((union DL_primitives *)buf)->info_ack;
  263:     switch (infop->dl_mac_type)
  264:     {
  265:         case DL_CSMACD:
  266:         case DL_ETHER:
  267:             l->link_type    = DLT_EN10MB;
  268:             l->link_offset  = 0xe;
  269:             break;
  270:         case DL_FDDI:
  271:             l->link_type    = DLT_FDDI;
  272:             l->link_offset  = 0x15;
  273:             break;
  274:         case DL_TPR:
  275:             l->link_type    = DLT_PRONET;
  276:             l->link_offset  = 0x16;
  277:             break;
  278:         default:
  279:             sprintf(l->err_buf, "%s(): unknown mac type 0x%lu\n", __func__,
  280:                     (u_int32_t) infop->dl_mac_type);
  281:             goto bad;
  282:     }
  283: 
  284: #ifdef	DLIOCRAW
  285:     /*
  286:      *  This is a non standard SunOS hack to get the ethernet header.
  287:      */
  288:     if (strioctl(l->fd, DLIOCRAW, 0, NULL) < 0)
  289:     {
  290:         sprintf(l->err_buf, "%s(): DLIOCRAW: %s\n", __func__, strerror(errno));
  291:         goto bad;
  292:     }
  293: #endif
  294: 
  295:     return (1);
  296: bad:
  297:     if (l->fd > 0)
  298:     {
  299:         close(l->fd);      /* this can fail ok */
  300:     }
  301:     return (-1);
  302: }
  303: 
  304: 
  305: static int
  306: send_request(int fd, int8_t *ptr, int len, int8_t *what, int8_t *ebuf,
  307: int flags)
  308: {
  309:     struct strbuf ctl;
  310: 
  311:     ctl.maxlen = 0;
  312:     ctl.len = len;
  313:     ctl.buf = ptr;
  314: 
  315:     if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0)
  316:     {
  317:         sprintf(ebuf, "%s(): putmsg \"%s\": %s\n", __func__, what,
  318:                 strerror(errno));
  319:         return (-1);
  320:     }
  321:     return (0);
  322: }
  323: 
  324: static int
  325: recv_ack(int fd, int size, const int8_t *what, int8_t *bufp, int8_t *ebuf)
  326: {
  327:     union DL_primitives *dlp;
  328:     struct strbuf ctl;
  329:     int flags;
  330: 
  331:     ctl.maxlen = MAXDLBUF;
  332:     ctl.len = 0;
  333:     ctl.buf = bufp;
  334: 
  335:     flags = 0;
  336:     if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0)
  337:     {
  338:         sprintf(ebuf, "%s(): %s getmsg: %s\n", __func__, what, strerror(errno));
  339:         return (-1);
  340:     }
  341: 
  342:     dlp = (union DL_primitives *)ctl.buf;
  343:     switch (dlp->dl_primitive)
  344:     {
  345:         case DL_INFO_ACK:
  346:         case DL_PHYS_ADDR_ACK:
  347:         case DL_BIND_ACK:
  348:         case DL_OK_ACK:
  349: #ifdef DL_HP_PPA_ACK
  350:         case DL_HP_PPA_ACK:
  351: #endif
  352:         /*
  353:          *  These are OK
  354:          */
  355:         break;
  356: 
  357:         case DL_ERROR_ACK:
  358:             switch (dlp->error_ack.dl_errno)
  359:             {
  360:                 case DL_BADPPA:
  361:                     sprintf(ebuf, "recv_ack: %s bad ppa (device unit)", what);
  362:                     break;
  363:                 case DL_SYSERR:
  364:                     sprintf(ebuf, "recv_ack: %s: %s",
  365:                         what, strerror(dlp->error_ack.dl_unix_errno));
  366:                     break;
  367:                 case DL_UNSUPPORTED:
  368:                     sprintf(ebuf,
  369:                         "recv_ack: %s: Service not supplied by provider", what);
  370:                     break;
  371:                 default:
  372:                     sprintf(ebuf, "recv_ack: %s error 0x%x", what,
  373:                         (bpf_u_int32)dlp->error_ack.dl_errno);
  374:                     break;
  375:             }
  376:             return (-1);
  377: 
  378:         default:
  379:             sprintf(ebuf, "recv_ack: %s unexpected primitive ack 0x%x ",
  380:                 what, (bpf_u_int32)dlp->dl_primitive);
  381:             return (-1);
  382:     }
  383: 
  384:     if (ctl.len < size)
  385:     {
  386:         sprintf(ebuf, "recv_ack: %s ack too small (%d < %d)",
  387:             what, ctl.len, size);
  388:         return (-1);
  389:     }
  390:     return (ctl.len);
  391: }
  392: 
  393: static int
  394: dlattachreq(int fd, bpf_u_int32 ppa, int8_t *ebuf)
  395: {
  396:     dl_attach_req_t req;
  397: 
  398:     req.dl_primitive = DL_ATTACH_REQ;
  399:     req.dl_ppa       = ppa;
  400: 
  401:     return (send_request(fd, (int8_t *)&req, sizeof(req), "attach", ebuf, 0));
  402: }
  403: 
  404: static int
  405: dlbindreq(int fd, bpf_u_int32 sap, int8_t *ebuf)
  406: {
  407: 
  408:     dl_bind_req_t	req;
  409: 
  410:     memset((int8_t *)&req, 0, sizeof(req));
  411:     req.dl_primitive = DL_BIND_REQ;
  412: #ifdef DL_HP_RAWDLS
  413:     req.dl_max_conind = 1;  /* XXX magic number */
  414:     /*
  415:      *  22 is INSAP as per the HP-UX DLPI Programmer's Guide
  416:      */
  417:     req.dl_sap = 22;
  418:     req.dl_service_mode = DL_HP_RAWDLS;
  419: #else
  420:     req.dl_sap = sap;
  421: #ifdef DL_CLDLS
  422:     req.dl_service_mode = DL_CLDLS;
  423: #endif
  424: #endif
  425:     return (send_request(fd, (int8_t *)&req, sizeof(req), "bind", ebuf, 0));
  426: }
  427: 
  428: static int
  429: dlbindack(int fd, int8_t *bufp, int8_t *ebuf)
  430: {
  431:     return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf));
  432: }
  433: 
  434: static int
  435: dlokack(int fd, const int8_t *what, int8_t *bufp, int8_t *ebuf)
  436: {
  437:     return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf));
  438: }
  439: 
  440: static int
  441: dlinforeq(int fd, int8_t *ebuf)
  442: {
  443:     dl_info_req_t req;
  444: 
  445:     req.dl_primitive = DL_INFO_REQ;
  446: 
  447:     return (send_request(fd, (int8_t *)&req, sizeof(req), "info", ebuf, 
  448:             RS_HIPRI));
  449: }
  450: 
  451: static int
  452: dlinfoack(int fd, int8_t *bufp, int8_t *ebuf)
  453: {
  454:     return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf));
  455: }
  456: 
  457: 
  458: #ifdef HAVE_SYS_BUFMOD_H
  459: static int
  460: strioctl(int fd, int cmd, int len, int8_t *dp)
  461: {
  462:     struct strioctl str;
  463:     int rc;
  464: 
  465:     str.ic_cmd    = cmd;
  466:     str.ic_timout = -1;
  467:     str.ic_len    = len;
  468:     str.ic_dp     = dp;
  469:     
  470:     rc = ioctl(fd, I_STR, &str);
  471:     if (rc < 0)
  472:     {
  473:         return (rc);
  474:     }
  475:     else
  476:     {
  477:         return (str.ic_len);
  478:     }
  479: }
  480: #endif
  481: 
  482: 
  483: #if (defined(DL_HP_PPA_ACK_OBS) && !defined(HAVE_HPUX11))
  484: /*
  485:  * Under HP-UX 10, we can ask for the ppa
  486:  */
  487: static int
  488: get_dlpi_ppa(register int fd, register const int8_t *device, register int unit,
  489: register int8_t *ebuf)
  490: {
  491:     register dl_hp_ppa_ack_t *ap;
  492:     register dl_hp_ppa_info_t *ip;
  493:     register int i;
  494:     register u_int32_t majdev;
  495:     dl_hp_ppa_req_t	req;
  496:     struct stat statbuf;
  497:     bpf_u_int32 buf[MAXDLBUF];
  498: 
  499:     if (stat(device, &statbuf) < 0)
  500:     {
  501:         sprintf(ebuf, "stat: %s: %s", device, strerror(errno));
  502:         return (-1);
  503:     }
  504:     majdev = major(statbuf.st_rdev);
  505: 
  506:     memset((int8_t *)&req, 0, sizeof(req));
  507:     req.dl_primitive = DL_HP_PPA_REQ;
  508: 
  509:     memset((int8_t *)buf, 0, sizeof(buf));
  510:     if (send_request(fd, (int8_t *)&req, sizeof(req), "hpppa", ebuf, 0) < 0 ||
  511:         recv_ack(fd, DL_HP_PPA_ACK_SIZE, "hpppa", (int8_t *)buf, ebuf) < 0)
  512:     {
  513:         return (-1);
  514:     }
  515: 
  516:     ap = (dl_hp_ppa_ack_t *)buf;
  517:     ip = (dl_hp_ppa_info_t *)((u_int8_t *)ap + ap->dl_offset);
  518: 
  519:     for (i = 0; i < ap->dl_count; i++)
  520:     {
  521:         if (ip->dl_mjr_num == majdev && ip->dl_instance_num == unit)
  522:         break;
  523: 
  524:         ip = (dl_hp_ppa_info_t *)((u_int8_t *)ip + ip->dl_next_offset);
  525:     }
  526: 
  527:     if (i == ap->dl_count)
  528:     {
  529:         sprintf(ebuf, "can't find PPA for %s", device);
  530:         return (-1);
  531:     }
  532: 
  533:     if (ip->dl_hdw_state == HDW_DEAD)
  534:     {
  535:         sprintf(ebuf, "%s: hardware state: DOWN\n", device);
  536:         return (-1);
  537:     }
  538:     return ((int)ip->dl_ppa);
  539: }
  540: #endif
  541: 
  542: #ifdef HAVE_HPUX9
  543: /*
  544:  * Under HP-UX 9, there is no good way to determine the ppa.
  545:  * So punt and read it from /dev/kmem.
  546:  */
  547: static struct nlist nl[] =
  548: {
  549: #define NL_IFNET 0
  550:     { "ifnet" },
  551:     { "" }
  552: };
  553: 
  554: static int8_t path_vmunix[] = "/hp-ux";
  555: 
  556: /*
  557:  *  Determine ppa number that specifies ifname
  558:  */
  559: static int
  560: get_dlpi_ppa(register int fd, register const int8_t *ifname, register int unit,
  561:     register int8_t *ebuf)
  562: {
  563:     register const int8_t *cp;
  564:     register int kd;
  565:     void *addr;
  566:     struct ifnet ifnet;
  567:     int8_t if_name[sizeof(ifnet.if_name)], tifname[32];
  568: 
  569:     cp = strrchr(ifname, '/');
  570:     if (cp != NULL)
  571:     {
  572:         ifname = cp + 1;
  573:     }
  574:     if (nlist(path_vmunix, &nl) < 0)
  575:     {
  576:         sprintf(ebuf, "nlist %s failed", path_vmunix);
  577:         return (-1);
  578:     }
  579: 
  580:     if (nl[NL_IFNET].n_value == 0)
  581:     {
  582:         sprintf(ebuf, "could't find %s kernel symbol", nl[NL_IFNET].n_name);
  583:         return (-1);
  584:     }
  585: 
  586:     kd = open("/dev/kmem", O_RDONLY);
  587:     if (kd < 0)
  588:     {
  589:         sprintf(ebuf, "kmem open: %s", strerror(errno));
  590:         return (-1);
  591:     }
  592: 
  593:     if (dlpi_kread(kd, nl[NL_IFNET].n_value, &addr, sizeof(addr), ebuf) < 0)
  594:     {
  595:         close(kd);
  596:         return (-1);
  597:     }
  598:     for (; addr != NULL; addr = ifnet.if_next)
  599:     {
  600:         if (dlpi_kread(kd, (off_t)addr, &ifnet, sizeof(ifnet), ebuf) < 0 ||
  601:             dlpi_kread(kd, (off_t)ifnet.if_name,
  602:             if_name, sizeof(if_name), ebuf) < 0)
  603:             {
  604:                 close(kd);
  605:                 return (-1);
  606:             }
  607:             sprintf(tifname, "%.*s%d",
  608:                 (int)sizeof(if_name), if_name, ifnet.if_unit);
  609:             if (strcmp(tifname, ifname) == 0)
  610:             {
  611:                 return (ifnet.if_index);
  612:             }
  613:     }
  614: 
  615:     sprintf(ebuf, "Can't find %s", ifname);
  616:     return (-1);
  617: }
  618: 
  619: static int
  620: dlpi_kread(register int fd, register off_t addr, register void *buf,
  621: register u_int len, register int8_t *ebuf)
  622: {
  623:     register int cc;
  624: 
  625:     if (lseek(fd, addr, SEEK_SET) < 0)
  626:     {
  627:         sprintf(ebuf, "lseek: %s", strerror(errno));
  628:         return (-1);
  629:     }
  630:     cc = read(fd, buf, len);
  631:     if (cc < 0)
  632:     {
  633:         sprintf(ebuf, "read: %s", strerror(errno));
  634:         return (-1);
  635:     }
  636:     else if (cc != len)
  637:     {
  638:         sprintf(ebuf, "int16_t read (%d != %d)", cc, len);
  639:         return (-1);
  640:     }
  641:     return (cc);
  642: }
  643: #endif
  644: 
  645: #define ETHERADDRL 6
  646: struct  EnetHeaderInfo
  647: {
  648:     struct libnet_ether_addr   DestEtherAddr;
  649:     u_int16_t EtherFrameType;
  650: };
  651: 
  652: 
  653: int
  654: libnet_close_link(libnet_t *l)
  655: {
  656:     if (close(l->fd) == 0)
  657:     {
  658:         free(l);
  659:         return (1);
  660:     }
  661:     else
  662:     {
  663:         free(l);
  664:         return (-1);
  665:     }
  666: }
  667: 
  668: #ifdef HAVE_HPUX11
  669: int 
  670: libnet_write_link(libnet_t *l, u_int8_t *packet, u_int32_t size)   
  671: {                                                             
  672:     struct strbuf data, ctl;
  673:     dl_hp_rawdata_req_t *rdata;
  674:     int c;                     
  675:                           
  676:     if (l == NULL)
  677:     {             
  678:         return (-1);           
  679:     }       
  680:             
  681:     rdata = (dl_hp_rawdata_req_t *)ctlbuf;
  682:     rdata->dl_primitive = DL_HP_RAWDATA_REQ; 
  683: 
  684:     /* send it */                                  
  685:     ctl.len = sizeof(dl_hp_rawdata_req_t);                         
  686:     ctl.maxlen = sizeof(dl_hp_rawdata_req_t);                      
  687:     ctl.buf = (int8_t *)rdata;
  688: 
  689:     data.maxlen = size;
  690:     data.len    = size;                                
  691:     data.buf    = packet;  
  692: 
  693:     c = putmsg(l->fd, &ctl, &data, 0);
  694:     if (c == -1)                      
  695:     {                    
  696:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  697:                 "libnet_write_link(): %d bytes written (%s)\n", c,
  698:                 strerror(errno));
  699:         return (-1);
  700:     }
  701:     else
  702:     {
  703:         return (size);
  704:     }                
  705: }   
  706: #else
  707: int
  708: libnet_write_link(libnet_t *l, u_int8_t *packet, u_int32_t size)
  709: {
  710:     int c;
  711:     struct strbuf data;
  712: 
  713:     if (l == NULL)
  714:     { 
  715:         return (-1);
  716:     } 
  717: 
  718:     data.maxlen = size;
  719:     data.len    = size;
  720:     data.buf    = packet;
  721: 
  722:     c = putmsg(l->fd, NULL, &data, 0);
  723:     if (c == -1)
  724:     {
  725:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  726:                 "libnet_write_link: %d bytes written (%s)\n", c,
  727:                 strerror(errno));
  728:         return (-1);
  729:     }
  730:     else
  731:     {
  732:         return (size);
  733:     }
  734: }
  735: #endif
  736: 
  737: struct libnet_ether_addr *
  738: libnet_get_hwaddr(libnet_t *l)
  739: {
  740:     int8_t buf[2048];
  741:     union DL_primitives *dlp;
  742:     struct libnet_ether_addr *eap;
  743: 
  744:     if (l == NULL)
  745:     { 
  746:         return (NULL);
  747:     }
  748: 
  749:     dlp = (union DL_primitives *)buf;
  750: 
  751:     dlp->physaddr_req.dl_primitive = DL_PHYS_ADDR_REQ;
  752:     dlp->physaddr_req.dl_addr_type = DL_CURR_PHYS_ADDR;
  753: 
  754:     if (send_request(l->fd, (int8_t *)dlp, DL_PHYS_ADDR_REQ_SIZE, "physaddr",
  755:             l->err_buf, 0) < 0)
  756:     {
  757:         return (NULL);
  758:     }
  759:     if (recv_ack(l->fd, DL_PHYS_ADDR_ACK_SIZE, "physaddr", (int8_t *)dlp,
  760:             l->err_buf) < 0)
  761:     {
  762:         return (NULL);
  763:     }
  764: 
  765:     eap = (struct libnet_ether_addr *)
  766:             ((int8_t *) dlp + dlp->physaddr_ack.dl_addr_offset);
  767:     return (eap);
  768: }   
  769: 
  770: /* EOF */

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