+

  "Fossies" - the Free Open Source Software Archive  

Member "libpcap-1.10.5/./pcap-dlpi.c" (30 Aug 2024, 49735 Bytes) of package /linux/misc/libpcap-1.10.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "pcap-dlpi.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.10.4_vs_1.10.5.

    1 /*
    2  * Copyright (c) 1993, 1994, 1995, 1996, 1997
    3  *  The Regents of the University of California.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that: (1) source code distributions
    7  * retain the above copyright notice and this paragraph in its entirety, (2)
    8  * distributions including binary code include the above copyright notice and
    9  * this paragraph in its entirety in the documentation or other materials
   10  * provided with the distribution, and (3) all advertising materials mentioning
   11  * features or use of this software display the following acknowledgement:
   12  * ``This product includes software developed by the University of California,
   13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
   14  * the University nor the names of its contributors may be used to endorse
   15  * or promote products derived from this software without specific prior
   16  * written permission.
   17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
   18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
   19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
   20  *
   21  * This code contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk),
   22  * University College London, and subsequently modified by
   23  * Guy Harris (guy@alum.mit.edu), Mark Pizzolato
   24  * <List-tcpdump-workers@subscriptions.pizzolato.net>,
   25  * Mark C. Brown (mbrown@hp.com), and Sagun Shakya <Sagun.Shakya@Sun.COM>.
   26  */
   27 
   28 /*
   29  * Packet capture routine for DLPI under SunOS 5, HP-UX 9/10/11, and AIX.
   30  *
   31  * Notes:
   32  *
   33  *    - The DLIOCRAW ioctl() is specific to SunOS.
   34  *
   35  *    - There is a bug in bufmod(7) such that setting the snapshot
   36  *      length results in data being left of the front of the packet.
   37  *
   38  *    - It might be desirable to use pfmod(7) to filter packets in the
   39  *      kernel when possible.
   40  *
   41  *    - An older version of the HP-UX DLPI Programmer's Guide, which
   42  *      I think was advertised as the 10.20 version, used to be available
   43  *      at
   44  *
   45  *            http://docs.hp.com/hpux/onlinedocs/B2355-90093/B2355-90093.html
   46  *
   47  *      but is no longer available; it can still be found at
   48  *
   49  *            http://h21007.www2.hp.com/dspp/files/unprotected/Drivers/Docs/Refs/B2355-90093.pdf
   50  *
   51  *      in PDF form.
   52  *
   53  *    - The HP-UX 10.x, 11.0, and 11i v1.6 version of the HP-UX DLPI
   54  *      Programmer's Guide, which I think was once advertised as the
   55  *      11.00 version is available at
   56  *
   57  *            http://docs.hp.com/en/B2355-90139/index.html
   58  *
   59  *    - The HP-UX 11i v2 version of the HP-UX DLPI Programmer's Guide
   60  *      is available at
   61  *
   62  *            http://docs.hp.com/en/B2355-90871/index.html
   63  *
   64  *    - All of the HP documents describe raw-mode services, which are
   65  *      what we use if DL_HP_RAWDLS is defined.  XXX - we use __hpux
   66  *      in some places to test for HP-UX, but use DL_HP_RAWDLS in
   67  *      other places; do we support any versions of HP-UX without
   68  *      DL_HP_RAWDLS?
   69  */
   70 
   71 #include <config.h>
   72 
   73 #include <sys/types.h>
   74 #include <sys/time.h>
   75 #ifdef HAVE_SYS_BUFMOD_H
   76 #include <sys/bufmod.h>
   77 #endif
   78 #include <sys/dlpi.h>
   79 #ifdef HAVE_SYS_DLPI_EXT_H
   80 #include <sys/dlpi_ext.h>
   81 #endif
   82 #ifdef HAVE_HPUX9
   83 #include <sys/socket.h>
   84 #endif
   85 #ifdef DL_HP_PPA_REQ
   86 #include <sys/stat.h>
   87 #endif
   88 #include <sys/stream.h>
   89 #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
   90 #include <sys/systeminfo.h>
   91 #endif
   92 
   93 #ifdef HAVE_HPUX9
   94 #include <net/if.h>
   95 #endif
   96 
   97 #ifdef HAVE_HPUX9
   98 #include <nlist.h>
   99 #endif
  100 #include <errno.h>
  101 #include <fcntl.h>
  102 #include <memory.h>
  103 #include <stdio.h>
  104 #include <stdlib.h>
  105 #include <string.h>
  106 #include <stropts.h>
  107 #include <unistd.h>
  108 #include <limits.h>
  109 
  110 #include "pcap-int.h"
  111 #include "dlpisubs.h"
  112 
  113 #ifdef HAVE_OS_PROTO_H
  114 #include "os-proto.h"
  115 #endif
  116 
  117 #if defined(__hpux)
  118   /*
  119    * HP-UX has a /dev/dlpi device; you open it and set the PPA of the actual
  120    * network device you want.
  121    */
  122   #define HAVE_DEV_DLPI
  123 #elif defined(_AIX)
  124   /*
  125    * AIX has a /dev/dlpi directory, with devices named after the interfaces
  126    * underneath it.
  127    */
  128   #define PCAP_DEV_PREFIX "/dev/dlpi"
  129 #elif defined(HAVE_SOLARIS)
  130   /*
  131    * Solaris has devices named after the interfaces underneath /dev.
  132    */
  133   #define PCAP_DEV_PREFIX "/dev"
  134 #endif
  135 
  136 #define MAXDLBUF    8192
  137 
  138 /* Forwards */
  139 static char *split_dname(char *, u_int *, char *);
  140 static int dl_doattach(int, int, char *);
  141 #ifdef DL_HP_RAWDLS
  142 static int dl_dohpuxbind(int, char *);
  143 #endif
  144 static int dlpromiscon(pcap_t *, bpf_u_int32);
  145 static int dlbindreq(int, bpf_u_int32, char *);
  146 static int dlbindack(int, char *, char *, int *);
  147 static int dlokack(int, const char *, char *, char *, int *);
  148 static int dlinforeq(int, char *);
  149 static int dlinfoack(int, char *, char *);
  150 
  151 #ifdef HAVE_DL_PASSIVE_REQ_T
  152 static void dlpassive(int, char *);
  153 #endif
  154 
  155 #ifdef DL_HP_RAWDLS
  156 static int dlrawdatareq(int, const u_char *, int);
  157 #endif
  158 static int recv_ack(int, int, const char *, char *, char *, int *);
  159 static char *dlstrerror(char *, size_t, bpf_u_int32);
  160 static char *dlprim(char *, size_t, bpf_u_int32);
  161 #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
  162 #define GET_RELEASE_BUFSIZE 32
  163 static void get_release(char *, size_t, bpf_u_int32 *, bpf_u_int32 *,
  164     bpf_u_int32 *);
  165 #endif
  166 static int send_request(int, char *, int, char *, char *);
  167 #ifdef HAVE_HPUX9
  168 static int dlpi_kread(int, off_t, void *, u_int, char *);
  169 #endif
  170 #ifdef HAVE_DEV_DLPI
  171 static int get_dlpi_ppa(int, const char *, u_int, u_int *, char *);
  172 #endif
  173 
  174 /*
  175  * Cast a buffer to "union DL_primitives" without provoking warnings
  176  * from the compiler.
  177  */
  178 #define MAKE_DL_PRIMITIVES(ptr) ((union DL_primitives *)(void *)(ptr))
  179 
  180 static int
  181 pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
  182 {
  183     int cc;
  184     u_char *bp;
  185     int flags;
  186     bpf_u_int32 ctlbuf[MAXDLBUF];
  187     struct strbuf ctl = {
  188         MAXDLBUF,
  189         0,
  190         (char *)ctlbuf
  191     };
  192     struct strbuf data;
  193 
  194     flags = 0;
  195     cc = p->cc;
  196     if (cc == 0) {
  197         data.buf = (char *)p->buffer + p->offset;
  198         data.maxlen = p->bufsize;
  199         data.len = 0;
  200         do {
  201             /*
  202              * Has "pcap_breakloop()" been called?
  203              */
  204             if (p->break_loop) {
  205                 /*
  206                  * Yes - clear the flag that indicates
  207                  * that it has, and return -2 to
  208                  * indicate that we were told to
  209                  * break out of the loop.
  210                  */
  211                 p->break_loop = 0;
  212                 return (-2);
  213             }
  214             /*
  215              * XXX - check for the DLPI primitive, which
  216              * would be DL_HP_RAWDATA_IND on HP-UX
  217              * if we're in raw mode?
  218              */
  219             ctl.buf = (char *)ctlbuf;
  220             ctl.maxlen = MAXDLBUF;
  221             ctl.len = 0;
  222             if (getmsg(p->fd, &ctl, &data, &flags) < 0) {
  223                 /* Don't choke when we get ptraced */
  224                 switch (errno) {
  225 
  226                 case EINTR:
  227                     cc = 0;
  228                     continue;
  229 
  230                 case EAGAIN:
  231                     return (0);
  232                 }
  233                 pcapint_fmt_errmsg_for_errno(p->errbuf,
  234                     sizeof(p->errbuf), errno, "getmsg");
  235                 return (-1);
  236             }
  237             cc = data.len;
  238         } while (cc == 0);
  239         bp = (u_char *)p->buffer + p->offset;
  240     } else
  241         bp = p->bp;
  242 
  243     return (pcap_process_pkts(p, callback, user, cnt, bp, cc));
  244 }
  245 
  246 static int
  247 pcap_inject_dlpi(pcap_t *p, const void *buf, int size)
  248 {
  249 #ifdef DL_HP_RAWDLS
  250     struct pcap_dlpi *pd = p->priv;
  251 #endif
  252     int ret;
  253 
  254 #if defined(DLIOCRAW)
  255     ret = write(p->fd, buf, size);
  256     if (ret == -1) {
  257         pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
  258             errno, "send");
  259         return (-1);
  260     }
  261 #elif defined(DL_HP_RAWDLS)
  262     if (pd->send_fd < 0) {
  263         snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
  264             "send: Output FD couldn't be opened");
  265         return (-1);
  266     }
  267     ret = dlrawdatareq(pd->send_fd, buf, size);
  268     if (ret == -1) {
  269         pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
  270             errno, "send");
  271         return (-1);
  272     }
  273     /*
  274      * putmsg() returns either 0 or -1; it doesn't indicate how
  275      * many bytes were written (presumably they were all written
  276      * or none of them were written).  OpenBSD's pcap_inject()
  277      * returns the number of bytes written, so, for API compatibility,
  278      * we return the number of bytes we were told to write.
  279      */
  280     ret = size;
  281 #else /* no raw mode */
  282     /*
  283      * XXX - this is a pain, because you might have to extract
  284      * the address from the packet and use it in a DL_UNITDATA_REQ
  285      * request.  That would be dependent on the link-layer type.
  286      *
  287      * I also don't know what SAP you'd have to bind the descriptor
  288      * to, or whether you'd need separate "receive" and "send" FDs,
  289      * nor do I know whether you'd need different bindings for
  290      * D/I/X Ethernet and 802.3, or for {FDDI,Token Ring} plus
  291      * 802.2 and {FDDI,Token Ring} plus 802.2 plus SNAP.
  292      *
  293      * So, for now, we just return a "you can't send" indication,
  294      * and leave it up to somebody with a DLPI-based system lacking
  295      * both DLIOCRAW and DL_HP_RAWDLS to supply code to implement
  296      * packet transmission on that system.  If they do, they should
  297      * send it to us - but should not send us code that assumes
  298      * Ethernet; if the code doesn't work on non-Ethernet interfaces,
  299      * it should check "p->linktype" and reject the send request if
  300      * it's anything other than DLT_EN10MB.
  301      */
  302     pcapint_strlcpy(p->errbuf, "send: Not supported on this version of this OS",
  303         PCAP_ERRBUF_SIZE);
  304     ret = -1;
  305 #endif /* raw mode */
  306     return (ret);
  307 }
  308 
  309 #ifndef DL_IPATM
  310 #define DL_IPATM    0x12    /* ATM Classical IP interface */
  311 #endif
  312 
  313 #ifdef HAVE_SOLARIS
  314 /*
  315  * For SunATM.
  316  */
  317 #ifndef A_GET_UNITS
  318 #define A_GET_UNITS (('A'<<8)|118)
  319 #endif /* A_GET_UNITS */
  320 #ifndef A_PROMISCON_REQ
  321 #define A_PROMISCON_REQ (('A'<<8)|121)
  322 #endif /* A_PROMISCON_REQ */
  323 #endif /* HAVE_SOLARIS */
  324 
  325 static void
  326 pcap_cleanup_dlpi(pcap_t *p)
  327 {
  328 #ifdef DL_HP_RAWDLS
  329     struct pcap_dlpi *pd = p->priv;
  330 
  331     if (pd->send_fd >= 0) {
  332         close(pd->send_fd);
  333         pd->send_fd = -1;
  334     }
  335 #endif
  336     pcapint_cleanup_live_common(p);
  337 }
  338 
  339 static int
  340 open_dlpi_device(const char *name, u_int *ppa, char *errbuf)
  341 {
  342     int status;
  343     char dname[100];
  344     char *cp;
  345     int fd;
  346 #ifdef HAVE_DEV_DLPI
  347     u_int unit;
  348 #else
  349     char dname2[100];
  350 #endif
  351 
  352 #ifdef HAVE_DEV_DLPI
  353     /*
  354     ** Remove any "/dev/" on the front of the device.
  355     */
  356     cp = strrchr(name, '/');
  357     if (cp == NULL)
  358         pcapint_strlcpy(dname, name, sizeof(dname));
  359     else
  360         pcapint_strlcpy(dname, cp + 1, sizeof(dname));
  361 
  362     /*
  363      * Split the device name into a device type name and a unit number;
  364      * chop off the unit number, so "dname" is just a device type name.
  365      */
  366     cp = split_dname(dname, &unit, errbuf);
  367     if (cp == NULL) {
  368         /*
  369          * split_dname() has filled in the error message.
  370          */
  371         return (PCAP_ERROR_NO_SUCH_DEVICE);
  372     }
  373     *cp = '\0';
  374 
  375     /*
  376      * Use "/dev/dlpi" as the device.
  377      *
  378      * XXX - HP's DLPI Programmer's Guide for HP-UX 11.00 says that
  379      * the "dl_mjr_num" field is for the "major number of interface
  380      * driver"; that's the major of "/dev/dlpi" on the system on
  381      * which I tried this, but there may be DLPI devices that
  382      * use a different driver, in which case we may need to
  383      * search "/dev" for the appropriate device with that major
  384      * device number, rather than hardwiring "/dev/dlpi".
  385      */
  386     cp = "/dev/dlpi";
  387     if ((fd = open(cp, O_RDWR)) < 0) {
  388         if (errno == EPERM || errno == EACCES) {
  389             status = PCAP_ERROR_PERM_DENIED;
  390             snprintf(errbuf, PCAP_ERRBUF_SIZE,
  391                 "Attempt to open %s failed with %s - root privilege may be required",
  392                 cp, (errno == EPERM) ? "EPERM" : "EACCES");
  393         } else {
  394             status = PCAP_ERROR;
  395             pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
  396                 errno, "Attempt to open %s failed", cp);
  397         }
  398         return (status);
  399     }
  400 
  401     /*
  402      * Get a table of all PPAs for that device, and search that
  403      * table for the specified device type name and unit number.
  404      */
  405     status = get_dlpi_ppa(fd, dname, unit, ppa, errbuf);
  406     if (status < 0) {
  407         close(fd);
  408         return (status);
  409     }
  410 #else
  411     /*
  412      * If the device name begins with "/", assume it begins with
  413      * the pathname of the directory containing the device to open;
  414      * otherwise, concatenate the device directory name and the
  415      * device name.
  416      */
  417     if (*name == '/')
  418         pcapint_strlcpy(dname, name, sizeof(dname));
  419     else
  420         snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX,
  421             name);
  422 
  423     /*
  424      * Get the unit number, and a pointer to the end of the device
  425      * type name.
  426      */
  427     cp = split_dname(dname, ppa, errbuf);
  428     if (cp == NULL) {
  429         /*
  430          * split_dname() has filled in the error message.
  431          */
  432         return (PCAP_ERROR_NO_SUCH_DEVICE);
  433     }
  434 
  435     /*
  436      * Make a copy of the device pathname, and then remove the unit
  437      * number from the device pathname.
  438      */
  439     pcapint_strlcpy(dname2, dname, sizeof(dname));
  440     *cp = '\0';
  441 
  442     /* Try device without unit number */
  443     if ((fd = open(dname, O_RDWR)) < 0) {
  444         if (errno != ENOENT) {
  445             if (errno == EPERM || errno == EACCES) {
  446                 status = PCAP_ERROR_PERM_DENIED;
  447                 snprintf(errbuf, PCAP_ERRBUF_SIZE,
  448                     "Attempt to open %s failed with %s - root privilege may be required",
  449                     dname,
  450                     (errno == EPERM) ? "EPERM" : "EACCES");
  451             } else {
  452                 status = PCAP_ERROR;
  453                 pcapint_fmt_errmsg_for_errno(errbuf,
  454                     PCAP_ERRBUF_SIZE, errno,
  455                     "Attempt to open %s failed", dname);
  456             }
  457             return (status);
  458         }
  459 
  460         /* Try again with unit number */
  461         if ((fd = open(dname2, O_RDWR)) < 0) {
  462             if (errno == ENOENT) {
  463                 status = PCAP_ERROR_NO_SUCH_DEVICE;
  464 
  465                 /*
  466                  * We provide an error message even
  467                  * for this error, for diagnostic
  468                  * purposes (so that, for example,
  469                  * the app can show the message if the
  470                  * user requests it).
  471                  *
  472                  * In it, we just report "No DLPI device
  473                  * found" with the device name, so people
  474                  * don't get confused and think, for example,
  475                  * that if they can't capture on "lo0"
  476                  * on Solaris prior to Solaris 11 the fix
  477                  * is to change libpcap (or the application
  478                  * that uses it) to look for something other
  479                  * than "/dev/lo0", as the fix is to use
  480                  * Solaris 11 or some operating system
  481                  * other than Solaris - you just *can't*
  482                  * capture on a loopback interface
  483                  * on Solaris prior to Solaris 11, the lack
  484                  * of a DLPI device for the loopback
  485                  * interface is just a symptom of that
  486                  * inability.
  487                  */
  488                 snprintf(errbuf, PCAP_ERRBUF_SIZE,
  489                     "%s: No DLPI device found", name);
  490             } else {
  491                 if (errno == EPERM || errno == EACCES) {
  492                     status = PCAP_ERROR_PERM_DENIED;
  493                     snprintf(errbuf, PCAP_ERRBUF_SIZE,
  494                         "Attempt to open %s failed with %s - root privilege may be required",
  495                         dname2,
  496                         (errno == EPERM) ? "EPERM" : "EACCES");
  497                 } else {
  498                     status = PCAP_ERROR;
  499                     pcapint_fmt_errmsg_for_errno(errbuf,
  500                         PCAP_ERRBUF_SIZE, errno,
  501                         "Attempt to open %s failed",
  502                         dname2);
  503                 }
  504             }
  505             return (status);
  506         }
  507         /* XXX Assume unit zero */
  508         *ppa = 0;
  509     }
  510 #endif
  511     return (fd);
  512 }
  513 
  514 static int
  515 pcap_activate_dlpi(pcap_t *p)
  516 {
  517 #ifdef DL_HP_RAWDLS
  518     struct pcap_dlpi *pd = p->priv;
  519 #endif
  520     int status = 0;
  521     int retv;
  522     u_int ppa;
  523 #ifdef HAVE_SOLARIS
  524     int isatm = 0;
  525 #endif
  526     register dl_info_ack_t *infop;
  527 #ifdef HAVE_SYS_BUFMOD_H
  528     bpf_u_int32 ss;
  529 #ifdef HAVE_SOLARIS
  530     char release[GET_RELEASE_BUFSIZE];
  531     bpf_u_int32 osmajor, osminor, osmicro;
  532 #endif
  533 #endif
  534     bpf_u_int32 buf[MAXDLBUF];
  535 
  536     p->fd = open_dlpi_device(p->opt.device, &ppa, p->errbuf);
  537     if (p->fd < 0) {
  538         status = p->fd;
  539         goto bad;
  540     }
  541 
  542 #ifdef DL_HP_RAWDLS
  543     /*
  544      * XXX - HP-UX 10.20 and 11.xx don't appear to support sending and
  545      * receiving packets on the same descriptor - you need separate
  546      * descriptors for sending and receiving, bound to different SAPs.
  547      *
  548      * If the open fails, we just leave -1 in "pd->send_fd" and reject
  549      * attempts to send packets, just as if, in pcap-bpf.c, we fail
  550      * to open the BPF device for reading and writing, we just try
  551      * to open it for reading only and, if that succeeds, just let
  552      * the send attempts fail.
  553      */
  554     pd->send_fd = open("/dev/dlpi", O_RDWR);
  555 #endif
  556 
  557     /*
  558     ** Attach if "style 2" provider
  559     */
  560     if (dlinforeq(p->fd, p->errbuf) < 0 ||
  561         dlinfoack(p->fd, (char *)buf, p->errbuf) < 0) {
  562         status = PCAP_ERROR;
  563         goto bad;
  564     }
  565     infop = &(MAKE_DL_PRIMITIVES(buf))->info_ack;
  566 #ifdef HAVE_SOLARIS
  567     if (infop->dl_mac_type == DL_IPATM)
  568         isatm = 1;
  569 #endif
  570     if (infop->dl_provider_style == DL_STYLE2) {
  571         retv = dl_doattach(p->fd, ppa, p->errbuf);
  572         if (retv < 0) {
  573             status = retv;
  574             goto bad;
  575         }
  576 #ifdef DL_HP_RAWDLS
  577         if (pd->send_fd >= 0) {
  578             retv = dl_doattach(pd->send_fd, ppa, p->errbuf);
  579             if (retv < 0) {
  580                 status = retv;
  581                 goto bad;
  582             }
  583         }
  584 #endif
  585     }
  586 
  587     if (p->opt.rfmon) {
  588         /*
  589          * This device exists, but we don't support monitor mode
  590          * any platforms that support DLPI.
  591          */
  592         status = PCAP_ERROR_RFMON_NOTSUP;
  593         goto bad;
  594     }
  595 
  596 #ifdef HAVE_DL_PASSIVE_REQ_T
  597     /*
  598      * Enable Passive mode to be able to capture on aggregated link.
  599      * Not supported in all Solaris versions.
  600      */
  601     dlpassive(p->fd, p->errbuf);
  602 #endif
  603     /*
  604     ** Bind (defer if using HP-UX 9 or HP-UX 10.20 or later, totally
  605     ** skip if using SINIX)
  606     */
  607 #if !defined(HAVE_HPUX9) && !defined(HAVE_HPUX10_20_OR_LATER) && !defined(sinix)
  608 #ifdef _AIX
  609     /*
  610     ** AIX.
  611     ** According to IBM's AIX Support Line, the dl_sap value
  612     ** should not be less than 0x600 (1536) for standard Ethernet.
  613     ** However, we seem to get DL_BADADDR - "DLSAP addr in improper
  614     ** format or invalid" - errors if we use 1537 on the "tr0"
  615     ** device, which, given that its name starts with "tr" and that
  616     ** it's IBM, probably means a Token Ring device.  (Perhaps we
  617     ** need to use 1537 on "/dev/dlpi/en" because that device is for
  618     ** D/I/X Ethernet, the "SAP" is actually an Ethernet type, and
  619     ** it rejects invalid Ethernet types.)
  620     **
  621     ** So if 1537 fails, we try 2, as Hyung Sik Yoon of IBM Korea
  622     ** says that works on Token Ring (he says that 0 does *not*
  623     ** work; perhaps that's considered an invalid LLC SAP value - I
  624     ** assume the SAP value in a DLPI bind is an LLC SAP for network
  625     ** types that use 802.2 LLC).
  626     */
  627     if ((dlbindreq(p->fd, 1537, p->errbuf) < 0 &&
  628          dlbindreq(p->fd, 2, p->errbuf) < 0) ||
  629          dlbindack(p->fd, (char *)buf, p->errbuf, NULL) < 0) {
  630         status = PCAP_ERROR;
  631         goto bad;
  632     }
  633 #elif defined(DL_HP_RAWDLS)
  634     /*
  635     ** HP-UX 10.0x and 10.1x.
  636     */
  637     if (dl_dohpuxbind(p->fd, p->errbuf) < 0) {
  638         status = PCAP_ERROR;
  639         goto bad;
  640     }
  641     if (pd->send_fd >= 0) {
  642         /*
  643         ** XXX - if this fails, just close send_fd and
  644         ** set it to -1, so that you can't send but can
  645         ** still receive?
  646         */
  647         if (dl_dohpuxbind(pd->send_fd, p->errbuf) < 0) {
  648             status = PCAP_ERROR;
  649             goto bad;
  650         }
  651     }
  652 #else /* neither AIX nor HP-UX */
  653     /*
  654     ** Not Sinix, and neither AIX nor HP-UX - Solaris, and any other
  655     ** OS using DLPI.
  656     **/
  657     if (dlbindreq(p->fd, 0, p->errbuf) < 0 ||
  658         dlbindack(p->fd, (char *)buf, p->errbuf, NULL) < 0) {
  659         status = PCAP_ERROR;
  660         goto bad;
  661     }
  662 #endif /* AIX vs. HP-UX vs. other */
  663 #endif /* !HP-UX 9 and !HP-UX 10.20 or later and !SINIX */
  664 
  665     /*
  666      * Turn a negative snapshot value (invalid), a snapshot value of
  667      * 0 (unspecified), or a value bigger than the normal maximum
  668      * value, into the maximum allowed value.
  669      *
  670      * If some application really *needs* a bigger snapshot
  671      * length, we should just increase MAXIMUM_SNAPLEN.
  672      */
  673     if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
  674         p->snapshot = MAXIMUM_SNAPLEN;
  675 
  676 #ifdef HAVE_SOLARIS
  677     if (isatm) {
  678         /*
  679         ** Have to turn on some special ATM promiscuous mode
  680         ** for SunATM.
  681         ** Do *NOT* turn regular promiscuous mode on; it doesn't
  682         ** help, and may break things.
  683         */
  684         if (strioctl(p->fd, A_PROMISCON_REQ, 0, NULL) < 0) {
  685             status = PCAP_ERROR;
  686             pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
  687                 errno, "A_PROMISCON_REQ");
  688             goto bad;
  689         }
  690     } else
  691 #endif
  692     if (p->opt.promisc) {
  693         /*
  694         ** Enable promiscuous (not necessary on send FD)
  695         */
  696         retv = dlpromiscon(p, DL_PROMISC_PHYS);
  697         if (retv < 0) {
  698             if (retv == PCAP_ERROR_PERM_DENIED)
  699                 status = PCAP_ERROR_PROMISC_PERM_DENIED;
  700             else
  701                 status = retv;
  702             goto bad;
  703         }
  704 
  705         /*
  706         ** Try to enable multicast (you would have thought
  707         ** promiscuous would be sufficient). (Skip if using
  708         ** HP-UX or SINIX) (Not necessary on send FD)
  709         */
  710 #if !defined(__hpux) && !defined(sinix)
  711         retv = dlpromiscon(p, DL_PROMISC_MULTI);
  712         if (retv < 0)
  713             status = PCAP_WARNING;
  714 #endif
  715     }
  716     /*
  717     ** Try to enable SAP promiscuity (when not in promiscuous mode
  718     ** when using HP-UX, when not doing SunATM on Solaris, and never
  719     ** under SINIX) (Not necessary on send FD)
  720     */
  721 #ifndef sinix
  722 #if defined(__hpux)
  723     /* HP-UX - only do this when not in promiscuous mode */
  724     if (!p->opt.promisc) {
  725 #elif defined(HAVE_SOLARIS)
  726     /* Solaris - don't do this on SunATM devices */
  727     if (!isatm) {
  728 #else
  729     /* Everything else (except for SINIX) - always do this */
  730     {
  731 #endif
  732         retv = dlpromiscon(p, DL_PROMISC_SAP);
  733         if (retv < 0) {
  734             if (p->opt.promisc) {
  735                 /*
  736                  * Not fatal, since the DL_PROMISC_PHYS mode
  737                  * worked.
  738                  *
  739                  * Report it as a warning, however.
  740                  */
  741                 status = PCAP_WARNING;
  742             } else {
  743                 /*
  744                  * Fatal.
  745                  */
  746                 status = retv;
  747                 goto bad;
  748             }
  749         }
  750     }
  751 #endif /* sinix */
  752 
  753     /*
  754     ** HP-UX 9, and HP-UX 10.20 or later, must bind after setting
  755     ** promiscuous options.
  756     */
  757 #if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20_OR_LATER)
  758     if (dl_dohpuxbind(p->fd, p->errbuf) < 0) {
  759         status = PCAP_ERROR;
  760         goto bad;
  761     }
  762     /*
  763     ** We don't set promiscuous mode on the send FD, but we'll defer
  764     ** binding it anyway, just to keep the HP-UX 9/10.20 or later
  765     ** code together.
  766     */
  767     if (pd->send_fd >= 0) {
  768         /*
  769         ** XXX - if this fails, just close send_fd and
  770         ** set it to -1, so that you can't send but can
  771         ** still receive?
  772         */
  773         if (dl_dohpuxbind(pd->send_fd, p->errbuf) < 0) {
  774             status = PCAP_ERROR;
  775             goto bad;
  776         }
  777     }
  778 #endif
  779 
  780     /*
  781     ** Determine link type
  782     ** XXX - get SAP length and address length as well, for use
  783     ** when sending packets.
  784     */
  785     if (dlinforeq(p->fd, p->errbuf) < 0 ||
  786         dlinfoack(p->fd, (char *)buf, p->errbuf) < 0) {
  787         status = PCAP_ERROR;
  788         goto bad;
  789     }
  790 
  791     infop = &(MAKE_DL_PRIMITIVES(buf))->info_ack;
  792     if (pcap_process_mactype(p, infop->dl_mac_type) != 0) {
  793         status = PCAP_ERROR;
  794         goto bad;
  795     }
  796 
  797 #ifdef  DLIOCRAW
  798     /*
  799     ** This is a non standard SunOS hack to get the full raw link-layer
  800     ** header.
  801     */
  802     if (strioctl(p->fd, DLIOCRAW, 0, NULL) < 0) {
  803         status = PCAP_ERROR;
  804         pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
  805             errno, "DLIOCRAW");
  806         goto bad;
  807     }
  808 #endif
  809 
  810 #ifdef HAVE_SYS_BUFMOD_H
  811     ss = p->snapshot;
  812 
  813     /*
  814     ** There is a bug in bufmod(7). When dealing with messages of
  815     ** less than snaplen size it strips data from the beginning not
  816     ** the end.
  817     **
  818     ** This bug is fixed in 5.3.2. Also, there is a patch available.
  819     ** Ask for bugid 1149065.
  820     */
  821 #ifdef HAVE_SOLARIS
  822     get_release(release, sizeof (release), &osmajor, &osminor, &osmicro);
  823     if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) &&
  824         getenv("BUFMOD_FIXED") == NULL) {
  825         snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
  826         "WARNING: bufmod is broken in SunOS %s; ignoring snaplen.",
  827             release);
  828         ss = 0;
  829         status = PCAP_WARNING;
  830     }
  831 #endif
  832 
  833     /* Push and configure bufmod. */
  834     if (pcap_conf_bufmod(p, ss) != 0) {
  835         status = PCAP_ERROR;
  836         goto bad;
  837     }
  838 #endif
  839 
  840     /*
  841     ** As the last operation flush the read side.
  842     */
  843     if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) {
  844         status = PCAP_ERROR;
  845         pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
  846             errno, "FLUSHR");
  847         goto bad;
  848     }
  849 
  850     /* Allocate data buffer. */
  851     if (pcap_alloc_databuf(p) != 0) {
  852         status = PCAP_ERROR;
  853         goto bad;
  854     }
  855 
  856     /*
  857      * Success.
  858      *
  859      * "p->fd" is an FD for a STREAMS device, so "select()" and
  860      * "poll()" should work on it.
  861      */
  862     p->selectable_fd = p->fd;
  863 
  864     p->read_op = pcap_read_dlpi;
  865     p->inject_op = pcap_inject_dlpi;
  866     p->setfilter_op = pcapint_install_bpf_program;  /* no kernel filtering */
  867     p->setdirection_op = NULL;  /* Not implemented.*/
  868     p->set_datalink_op = NULL;  /* can't change data link type */
  869     p->getnonblock_op = pcapint_getnonblock_fd;
  870     p->setnonblock_op = pcapint_setnonblock_fd;
  871     p->stats_op = pcap_stats_dlpi;
  872     p->cleanup_op = pcap_cleanup_dlpi;
  873 
  874     return (status);
  875 bad:
  876     pcap_cleanup_dlpi(p);
  877     return (status);
  878 }
  879 
  880 /*
  881  * Split a device name into a device type name and a unit number;
  882  * return the a pointer to the beginning of the unit number, which
  883  * is the end of the device type name, and set "*unitp" to the unit
  884  * number.
  885  *
  886  * Returns NULL on error, and fills "ebuf" with an error message.
  887  */
  888 static char *
  889 split_dname(char *device, u_int *unitp, char *ebuf)
  890 {
  891     char *cp;
  892     char *eos;
  893     long unit;
  894 
  895     /*
  896      * Look for a number at the end of the device name string.
  897      */
  898     cp = device + strlen(device) - 1;
  899     if (*cp < '0' || *cp > '9') {
  900         snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s missing unit number",
  901             device);
  902         return (NULL);
  903     }
  904 
  905     /* Digits at end of string are unit number */
  906     while (cp-1 >= device && *(cp-1) >= '0' && *(cp-1) <= '9')
  907         cp--;
  908 
  909     errno = 0;
  910     unit = strtol(cp, &eos, 10);
  911     if (*eos != '\0') {
  912         snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s bad unit number", device);
  913         return (NULL);
  914     }
  915     if (errno == ERANGE || unit > INT_MAX) {
  916         snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number too large",
  917             device);
  918         return (NULL);
  919     }
  920     if (unit < 0) {
  921         snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number is negative",
  922             device);
  923         return (NULL);
  924     }
  925     *unitp = (u_int)unit;
  926     return (cp);
  927 }
  928 
  929 static int
  930 dl_doattach(int fd, int ppa, char *ebuf)
  931 {
  932     dl_attach_req_t req;
  933     bpf_u_int32 buf[MAXDLBUF];
  934     int err;
  935 
  936     req.dl_primitive = DL_ATTACH_REQ;
  937     req.dl_ppa = ppa;
  938     if (send_request(fd, (char *)&req, sizeof(req), "attach", ebuf) < 0)
  939         return (PCAP_ERROR);
  940 
  941     err = dlokack(fd, "attach", (char *)buf, ebuf, NULL);
  942     if (err < 0)
  943         return (err);
  944     return (0);
  945 }
  946 
  947 #ifdef DL_HP_RAWDLS
  948 static int
  949 dl_dohpuxbind(int fd, char *ebuf)
  950 {
  951     int hpsap;
  952     int uerror;
  953     bpf_u_int32 buf[MAXDLBUF];
  954 
  955     /*
  956      * XXX - we start at 22 because we used to use only 22, but
  957      * that was just because that was the value used in some
  958      * sample code from HP.  With what value *should* we start?
  959      * Does it matter, given that we're enabling SAP promiscuity
  960      * on the input FD?
  961      */
  962     hpsap = 22;
  963     for (;;) {
  964         if (dlbindreq(fd, hpsap, ebuf) < 0)
  965             return (-1);
  966         if (dlbindack(fd, (char *)buf, ebuf, &uerror) >= 0)
  967             break;
  968         /*
  969          * For any error other than a UNIX EBUSY, give up.
  970          */
  971         if (uerror != EBUSY) {
  972             /*
  973              * dlbindack() has already filled in ebuf for
  974              * this error.
  975              */
  976             return (-1);
  977         }
  978 
  979         /*
  980          * For EBUSY, try the next SAP value; that means that
  981          * somebody else is using that SAP.  Clear ebuf so
  982          * that application doesn't report the "Device busy"
  983          * error as a warning.
  984          */
  985         *ebuf = '\0';
  986         hpsap++;
  987         if (hpsap > 100) {
  988             pcapint_strlcpy(ebuf,
  989                 "All SAPs from 22 through 100 are in use",
  990                 PCAP_ERRBUF_SIZE);
  991             return (-1);
  992         }
  993     }
  994     return (0);
  995 }
  996 #endif
  997 
  998 #define STRINGIFY(n)    #n
  999 
 1000 static int
 1001 dlpromiscon(pcap_t *p, bpf_u_int32 level)
 1002 {
 1003     dl_promiscon_req_t req;
 1004     bpf_u_int32 buf[MAXDLBUF];
 1005     int err;
 1006     int uerror;
 1007 
 1008     req.dl_primitive = DL_PROMISCON_REQ;
 1009     req.dl_level = level;
 1010     if (send_request(p->fd, (char *)&req, sizeof(req), "promiscon",
 1011         p->errbuf) < 0)
 1012         return (PCAP_ERROR);
 1013     err = dlokack(p->fd, "promiscon" STRINGIFY(level), (char *)buf,
 1014         p->errbuf, &uerror);
 1015     if (err < 0) {
 1016         if (err == PCAP_ERROR_PERM_DENIED) {
 1017             snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 1018                 "Attempt to set promiscuous mode failed with %s - root privilege may be required",
 1019                 (uerror == EPERM) ? "EPERM" : "EACCES");
 1020             err = PCAP_ERROR_PROMISC_PERM_DENIED;
 1021         }
 1022         return (err);
 1023     }
 1024     return (0);
 1025 }
 1026 
 1027 /*
 1028  * Not all interfaces are DLPI interfaces, and thus not all interfaces
 1029  * can be opened with DLPI (for example, the loopback interface is not
 1030  * a DLPI interface on Solaris prior to Solaris 11), so try to open
 1031  * the specified interface; return 0 if we fail with PCAP_ERROR_NO_SUCH_DEVICE
 1032  * and 1 otherwise.
 1033  */
 1034 static int
 1035 is_dlpi_interface(const char *name)
 1036 {
 1037     int fd;
 1038     u_int ppa;
 1039     char errbuf[PCAP_ERRBUF_SIZE];
 1040 
 1041     fd = open_dlpi_device(name, &ppa, errbuf);
 1042     if (fd < 0) {
 1043         /*
 1044          * Error - was it PCAP_ERROR_NO_SUCH_DEVICE?
 1045          */
 1046         if (fd == PCAP_ERROR_NO_SUCH_DEVICE) {
 1047             /*
 1048              * Yes, so we can't open this because it's
 1049              * not a DLPI interface.
 1050              */
 1051             return (0);
 1052         }
 1053         /*
 1054          * No, so, in the case where there's a single DLPI
 1055          * device for all interfaces of this type ("style
 1056          * 2" providers?), we don't know whether it's a DLPI
 1057          * interface or not, as we didn't try an attach.
 1058          * Say it is a DLPI device, so that the user can at
 1059          * least try to open it and report the error (which
 1060          * is probably "you don't have permission to open that
 1061          * DLPI device"; reporting those interfaces means
 1062          * users will ask "why am I getting a permissions error
 1063          * when I try to capture" rather than "why am I not
 1064          * seeing any interfaces", making the underlying problem
 1065          * clearer).
 1066          */
 1067         return (1);
 1068     }
 1069 
 1070     /*
 1071      * Success.
 1072      */
 1073     close(fd);
 1074     return (1);
 1075 }
 1076 
 1077 static int
 1078 get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
 1079 {
 1080     /*
 1081      * Nothing we can do other than mark loopback devices as "the
 1082      * connected/disconnected status doesn't apply".
 1083      *
 1084      * XXX - on Solaris, can we do what the dladm command does,
 1085      * i.e. get a connected/disconnected indication from a kstat?
 1086      * (Note that you can also get the link speed, and possibly
 1087      * other information, from a kstat as well.)
 1088      */
 1089     if (*flags & PCAP_IF_LOOPBACK) {
 1090         /*
 1091          * Loopback devices aren't wireless, and "connected"/
 1092          * "disconnected" doesn't apply to them.
 1093          */
 1094         *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
 1095         return (0);
 1096     }
 1097     return (0);
 1098 }
 1099 
 1100 int
 1101 pcapint_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
 1102 {
 1103 #ifdef HAVE_SOLARIS
 1104     int fd;
 1105     union {
 1106         u_int nunits;
 1107         char pad[516];  /* XXX - must be at least 513; is 516
 1108                    in "atmgetunits" */
 1109     } buf;
 1110     char baname[2+1+1];
 1111     u_int i;
 1112 #endif
 1113 
 1114     /*
 1115      * Get the list of regular interfaces first.
 1116      */
 1117     if (pcapint_findalldevs_interfaces(devlistp, errbuf, is_dlpi_interface,
 1118         get_if_flags) == -1)
 1119         return (-1);    /* failure */
 1120 
 1121 #ifdef HAVE_SOLARIS
 1122     /*
 1123      * We may have to do special magic to get ATM devices.
 1124      */
 1125     if ((fd = open("/dev/ba", O_RDWR)) < 0) {
 1126         /*
 1127          * We couldn't open the "ba" device.
 1128          * For now, just give up; perhaps we should
 1129          * return an error if the problem is neither
 1130          * a "that device doesn't exist" error (ENOENT,
 1131          * ENXIO, etc.) or a "you're not allowed to do
 1132          * that" error (EPERM, EACCES).
 1133          */
 1134         return (0);
 1135     }
 1136 
 1137     if (strioctl(fd, A_GET_UNITS, sizeof(buf), (char *)&buf) < 0) {
 1138         pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
 1139             errno, "A_GET_UNITS");
 1140         return (-1);
 1141     }
 1142     for (i = 0; i < buf.nunits; i++) {
 1143         snprintf(baname, sizeof baname, "ba%u", i);
 1144         /*
 1145          * XXX - is there a notion of "up" and "running"?
 1146          * And is there a way to determine whether the
 1147          * interface is plugged into a network?
 1148          */
 1149         if (pcapint_add_dev(devlistp, baname, 0, NULL, errbuf) == NULL)
 1150             return (-1);
 1151     }
 1152 #endif
 1153 
 1154     return (0);
 1155 }
 1156 
 1157 static int
 1158 send_request(int fd, char *ptr, int len, char *what, char *ebuf)
 1159 {
 1160     struct  strbuf  ctl;
 1161     int flags;
 1162 
 1163     ctl.maxlen = 0;
 1164     ctl.len = len;
 1165     ctl.buf = ptr;
 1166 
 1167     flags = 0;
 1168     if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0) {
 1169         pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
 1170             errno, "send_request: putmsg \"%s\"", what);
 1171         return (-1);
 1172     }
 1173     return (0);
 1174 }
 1175 
 1176 static int
 1177 recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror)
 1178 {
 1179     union   DL_primitives   *dlp;
 1180     struct  strbuf  ctl;
 1181     int flags;
 1182     char    errmsgbuf[PCAP_ERRBUF_SIZE];
 1183     char    dlprimbuf[64];
 1184 
 1185     /*
 1186      * Clear out "*uerror", so it's only set for DL_ERROR_ACK/DL_SYSERR,
 1187      * making that the only place where EBUSY is treated specially.
 1188      */
 1189     if (uerror != NULL)
 1190         *uerror = 0;
 1191 
 1192     ctl.maxlen = MAXDLBUF;
 1193     ctl.len = 0;
 1194     ctl.buf = bufp;
 1195 
 1196     flags = 0;
 1197     if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) {
 1198         pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
 1199             errno, "recv_ack: %s getmsg", what);
 1200         return (PCAP_ERROR);
 1201     }
 1202 
 1203     dlp = MAKE_DL_PRIMITIVES(ctl.buf);
 1204     switch (dlp->dl_primitive) {
 1205 
 1206     case DL_INFO_ACK:
 1207     case DL_BIND_ACK:
 1208     case DL_OK_ACK:
 1209 #ifdef DL_HP_PPA_ACK
 1210     case DL_HP_PPA_ACK:
 1211 #endif
 1212         /* These are OK */
 1213         break;
 1214 
 1215     case DL_ERROR_ACK:
 1216         switch (dlp->error_ack.dl_errno) {
 1217 
 1218         case DL_SYSERR:
 1219             if (uerror != NULL)
 1220                 *uerror = dlp->error_ack.dl_unix_errno;
 1221             pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
 1222                 dlp->error_ack.dl_unix_errno,
 1223                 "recv_ack: %s: UNIX error", what);
 1224             if (dlp->error_ack.dl_unix_errno == EPERM ||
 1225                 dlp->error_ack.dl_unix_errno == EACCES)
 1226                 return (PCAP_ERROR_PERM_DENIED);
 1227             break;
 1228 
 1229         default:
 1230             /*
 1231              * Neither EPERM nor EACCES.
 1232              */
 1233             snprintf(ebuf, PCAP_ERRBUF_SIZE,
 1234                 "recv_ack: %s: %s", what,
 1235                 dlstrerror(errmsgbuf, sizeof (errmsgbuf), dlp->error_ack.dl_errno));
 1236             if (dlp->error_ack.dl_errno == DL_BADPPA)
 1237                 return (PCAP_ERROR_NO_SUCH_DEVICE);
 1238             else if (dlp->error_ack.dl_errno == DL_ACCESS)
 1239                 return (PCAP_ERROR_PERM_DENIED);
 1240             break;
 1241         }
 1242         return (PCAP_ERROR);
 1243 
 1244     default:
 1245         snprintf(ebuf, PCAP_ERRBUF_SIZE,
 1246             "recv_ack: %s: Unexpected primitive ack %s",
 1247             what, dlprim(dlprimbuf, sizeof (dlprimbuf), dlp->dl_primitive));
 1248         return (PCAP_ERROR);
 1249     }
 1250 
 1251     if (ctl.len < size) {
 1252         snprintf(ebuf, PCAP_ERRBUF_SIZE,
 1253             "recv_ack: %s: Ack too small (%d < %d)",
 1254             what, ctl.len, size);
 1255         return (PCAP_ERROR);
 1256     }
 1257     return (ctl.len);
 1258 }
 1259 
 1260 static char *
 1261 dlstrerror(char *errbuf, size_t errbufsize, bpf_u_int32 dl_errno)
 1262 {
 1263     switch (dl_errno) {
 1264 
 1265     case DL_ACCESS:
 1266         return ("Improper permissions for request");
 1267 
 1268     case DL_BADADDR:
 1269         return ("DLSAP addr in improper format or invalid");
 1270 
 1271     case DL_BADCORR:
 1272         return ("Seq number not from outstand DL_CONN_IND");
 1273 
 1274     case DL_BADDATA:
 1275         return ("User data exceeded provider limit");
 1276 
 1277     case DL_BADPPA:
 1278 #ifdef HAVE_DEV_DLPI
 1279         /*
 1280          * With a single "/dev/dlpi" device used for all
 1281          * DLPI providers, PPAs have nothing to do with
 1282          * unit numbers.
 1283          */
 1284         return ("Specified PPA was invalid");
 1285 #else
 1286         /*
 1287          * We have separate devices for separate devices;
 1288          * the PPA is just the unit number.
 1289          */
 1290         return ("Specified PPA (device unit) was invalid");
 1291 #endif
 1292 
 1293     case DL_BADPRIM:
 1294         return ("Primitive received not known by provider");
 1295 
 1296     case DL_BADQOSPARAM:
 1297         return ("QOS parameters contained invalid values");
 1298 
 1299     case DL_BADQOSTYPE:
 1300         return ("QOS structure type is unknown/unsupported");
 1301 
 1302     case DL_BADSAP:
 1303         return ("Bad LSAP selector");
 1304 
 1305     case DL_BADTOKEN:
 1306         return ("Token used not an active stream");
 1307 
 1308     case DL_BOUND:
 1309         return ("Attempted second bind with dl_max_conind");
 1310 
 1311     case DL_INITFAILED:
 1312         return ("Physical link initialization failed");
 1313 
 1314     case DL_NOADDR:
 1315         return ("Provider couldn't allocate alternate address");
 1316 
 1317     case DL_NOTINIT:
 1318         return ("Physical link not initialized");
 1319 
 1320     case DL_OUTSTATE:
 1321         return ("Primitive issued in improper state");
 1322 
 1323     case DL_SYSERR:
 1324         return ("UNIX system error occurred");
 1325 
 1326     case DL_UNSUPPORTED:
 1327         return ("Requested service not supplied by provider");
 1328 
 1329     case DL_UNDELIVERABLE:
 1330         return ("Previous data unit could not be delivered");
 1331 
 1332     case DL_NOTSUPPORTED:
 1333         return ("Primitive is known but not supported");
 1334 
 1335     case DL_TOOMANY:
 1336         return ("Limit exceeded");
 1337 
 1338     case DL_NOTENAB:
 1339         return ("Promiscuous mode not enabled");
 1340 
 1341     case DL_BUSY:
 1342         return ("Other streams for PPA in post-attached");
 1343 
 1344     case DL_NOAUTO:
 1345         return ("Automatic handling XID&TEST not supported");
 1346 
 1347     case DL_NOXIDAUTO:
 1348         return ("Automatic handling of XID not supported");
 1349 
 1350     case DL_NOTESTAUTO:
 1351         return ("Automatic handling of TEST not supported");
 1352 
 1353     case DL_XIDAUTO:
 1354         return ("Automatic handling of XID response");
 1355 
 1356     case DL_TESTAUTO:
 1357         return ("Automatic handling of TEST response");
 1358 
 1359     case DL_PENDING:
 1360         return ("Pending outstanding connect indications");
 1361 
 1362     default:
 1363         snprintf(errbuf, errbufsize, "Error %02x", dl_errno);
 1364         return (errbuf);
 1365     }
 1366 }
 1367 
 1368 static char *
 1369 dlprim(char *primbuf, size_t primbufsize, bpf_u_int32 prim)
 1370 {
 1371     switch (prim) {
 1372 
 1373     case DL_INFO_REQ:
 1374         return ("DL_INFO_REQ");
 1375 
 1376     case DL_INFO_ACK:
 1377         return ("DL_INFO_ACK");
 1378 
 1379     case DL_ATTACH_REQ:
 1380         return ("DL_ATTACH_REQ");
 1381 
 1382     case DL_DETACH_REQ:
 1383         return ("DL_DETACH_REQ");
 1384 
 1385     case DL_BIND_REQ:
 1386         return ("DL_BIND_REQ");
 1387 
 1388     case DL_BIND_ACK:
 1389         return ("DL_BIND_ACK");
 1390 
 1391     case DL_UNBIND_REQ:
 1392         return ("DL_UNBIND_REQ");
 1393 
 1394     case DL_OK_ACK:
 1395         return ("DL_OK_ACK");
 1396 
 1397     case DL_ERROR_ACK:
 1398         return ("DL_ERROR_ACK");
 1399 
 1400     case DL_SUBS_BIND_REQ:
 1401         return ("DL_SUBS_BIND_REQ");
 1402 
 1403     case DL_SUBS_BIND_ACK:
 1404         return ("DL_SUBS_BIND_ACK");
 1405 
 1406     case DL_UNITDATA_REQ:
 1407         return ("DL_UNITDATA_REQ");
 1408 
 1409     case DL_UNITDATA_IND:
 1410         return ("DL_UNITDATA_IND");
 1411 
 1412     case DL_UDERROR_IND:
 1413         return ("DL_UDERROR_IND");
 1414 
 1415     case DL_UDQOS_REQ:
 1416         return ("DL_UDQOS_REQ");
 1417 
 1418     case DL_CONNECT_REQ:
 1419         return ("DL_CONNECT_REQ");
 1420 
 1421     case DL_CONNECT_IND:
 1422         return ("DL_CONNECT_IND");
 1423 
 1424     case DL_CONNECT_RES:
 1425         return ("DL_CONNECT_RES");
 1426 
 1427     case DL_CONNECT_CON:
 1428         return ("DL_CONNECT_CON");
 1429 
 1430     case DL_TOKEN_REQ:
 1431         return ("DL_TOKEN_REQ");
 1432 
 1433     case DL_TOKEN_ACK:
 1434         return ("DL_TOKEN_ACK");
 1435 
 1436     case DL_DISCONNECT_REQ:
 1437         return ("DL_DISCONNECT_REQ");
 1438 
 1439     case DL_DISCONNECT_IND:
 1440         return ("DL_DISCONNECT_IND");
 1441 
 1442     case DL_RESET_REQ:
 1443         return ("DL_RESET_REQ");
 1444 
 1445     case DL_RESET_IND:
 1446         return ("DL_RESET_IND");
 1447 
 1448     case DL_RESET_RES:
 1449         return ("DL_RESET_RES");
 1450 
 1451     case DL_RESET_CON:
 1452         return ("DL_RESET_CON");
 1453 
 1454     default:
 1455         snprintf(primbuf, primbufsize, "unknown primitive 0x%x",
 1456             prim);
 1457         return (primbuf);
 1458     }
 1459 }
 1460 
 1461 static int
 1462 dlbindreq(int fd, bpf_u_int32 sap, char *ebuf)
 1463 {
 1464 
 1465     dl_bind_req_t   req;
 1466 
 1467     memset((char *)&req, 0, sizeof(req));
 1468     req.dl_primitive = DL_BIND_REQ;
 1469     /* XXX - what if neither of these are defined? */
 1470 #if defined(DL_HP_RAWDLS)
 1471     req.dl_max_conind = 1;          /* XXX magic number */
 1472     req.dl_service_mode = DL_HP_RAWDLS;
 1473 #elif defined(DL_CLDLS)
 1474     req.dl_service_mode = DL_CLDLS;
 1475 #endif
 1476     req.dl_sap = sap;
 1477 
 1478     return (send_request(fd, (char *)&req, sizeof(req), "bind", ebuf));
 1479 }
 1480 
 1481 static int
 1482 dlbindack(int fd, char *bufp, char *ebuf, int *uerror)
 1483 {
 1484 
 1485     return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf, uerror));
 1486 }
 1487 
 1488 static int
 1489 dlokack(int fd, const char *what, char *bufp, char *ebuf, int *uerror)
 1490 {
 1491 
 1492     return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf, uerror));
 1493 }
 1494 
 1495 
 1496 static int
 1497 dlinforeq(int fd, char *ebuf)
 1498 {
 1499     dl_info_req_t req;
 1500 
 1501     req.dl_primitive = DL_INFO_REQ;
 1502 
 1503     return (send_request(fd, (char *)&req, sizeof(req), "info", ebuf));
 1504 }
 1505 
 1506 static int
 1507 dlinfoack(int fd, char *bufp, char *ebuf)
 1508 {
 1509 
 1510     return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf, NULL));
 1511 }
 1512 
 1513 #ifdef HAVE_DL_PASSIVE_REQ_T
 1514 /*
 1515  * Enable DLPI passive mode. We do not care if this request fails, as this
 1516  * indicates the underlying DLPI device does not support link aggregation.
 1517  */
 1518 static void
 1519 dlpassive(int fd, char *ebuf)
 1520 {
 1521     dl_passive_req_t req;
 1522     bpf_u_int32 buf[MAXDLBUF];
 1523 
 1524     req.dl_primitive = DL_PASSIVE_REQ;
 1525 
 1526     if (send_request(fd, (char *)&req, sizeof(req), "dlpassive", ebuf) == 0)
 1527         (void) dlokack(fd, "dlpassive", (char *)buf, ebuf, NULL);
 1528 }
 1529 #endif
 1530 
 1531 #ifdef DL_HP_RAWDLS
 1532 /*
 1533  * There's an ack *if* there's an error.
 1534  */
 1535 static int
 1536 dlrawdatareq(int fd, const u_char *datap, int datalen)
 1537 {
 1538     struct strbuf ctl, data;
 1539     long buf[MAXDLBUF]; /* XXX - char? */
 1540     union DL_primitives *dlp;
 1541     int dlen;
 1542 
 1543     dlp = MAKE_DL_PRIMITIVES(buf);
 1544 
 1545     dlp->dl_primitive = DL_HP_RAWDATA_REQ;
 1546     dlen = DL_HP_RAWDATA_REQ_SIZE;
 1547 
 1548     /*
 1549      * HP's documentation doesn't appear to show us supplying any
 1550      * address pointed to by the control part of the message.
 1551      * I think that's what raw mode means - you just send the raw
 1552      * packet, you don't specify where to send it to, as that's
 1553      * implied by the destination address.
 1554      */
 1555     ctl.maxlen = 0;
 1556     ctl.len = dlen;
 1557     ctl.buf = (void *)buf;
 1558 
 1559     data.maxlen = 0;
 1560     data.len = datalen;
 1561     data.buf = (void *)datap;
 1562 
 1563     return (putmsg(fd, &ctl, &data, 0));
 1564 }
 1565 #endif /* DL_HP_RAWDLS */
 1566 
 1567 #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
 1568 static void
 1569 get_release(char *buf, size_t bufsize, bpf_u_int32 *majorp,
 1570     bpf_u_int32 *minorp, bpf_u_int32 *microp)
 1571 {
 1572     char *cp;
 1573 
 1574     *majorp = 0;
 1575     *minorp = 0;
 1576     *microp = 0;
 1577     if (sysinfo(SI_RELEASE, buf, bufsize) < 0) {
 1578         pcapint_strlcpy(buf, "?", bufsize);
 1579         return;
 1580     }
 1581     cp = buf;
 1582     if (!PCAP_ISDIGIT((unsigned char)*cp))
 1583         return;
 1584     *majorp = strtol(cp, &cp, 10);
 1585     if (*cp++ != '.')
 1586         return;
 1587     *minorp =  strtol(cp, &cp, 10);
 1588     if (*cp++ != '.')
 1589         return;
 1590     *microp =  strtol(cp, &cp, 10);
 1591 }
 1592 #endif
 1593 
 1594 #ifdef DL_HP_PPA_REQ
 1595 /*
 1596  * Under HP-UX 10 and HP-UX 11, we can ask for the ppa
 1597  */
 1598 
 1599 
 1600 /*
 1601  * Determine ppa number that specifies ifname.
 1602  *
 1603  * If the "dl_hp_ppa_info_t" doesn't have a "dl_module_id_1" member,
 1604  * the code that's used here is the old code for HP-UX 10.x.
 1605  *
 1606  * However, HP-UX 10.20, at least, appears to have such a member
 1607  * in its "dl_hp_ppa_info_t" structure, so the new code is used.
 1608  * The new code didn't work on an old 10.20 system on which Rick
 1609  * Jones of HP tried it, but with later patches installed, it
 1610  * worked - it appears that the older system had those members but
 1611  * didn't put anything in them, so, if the search by name fails, we
 1612  * do the old search.
 1613  *
 1614  * Rick suggests that making sure your system is "up on the latest
 1615  * lancommon/DLPI/driver patches" is probably a good idea; it'd fix
 1616  * that problem, as well as allowing libpcap to see packets sent
 1617  * from the system on which the libpcap application is being run.
 1618  * (On 10.20, in addition to getting the latest patches, you need
 1619  * to turn the kernel "lanc_outbound_promisc_flag" flag on with ADB;
 1620  * a posting to "comp.sys.hp.hpux" at
 1621  *
 1622  *  http://www.deja.com/[ST_rn=ps]/getdoc.xp?AN=558092266
 1623  *
 1624  * says that, to see the machine's outgoing traffic, you'd need to
 1625  * apply the right patches to your system, and also set that variable
 1626  * with:
 1627 
 1628 echo 'lanc_outbound_promisc_flag/W1' | /usr/bin/adb -w /stand/vmunix /dev/kmem
 1629 
 1630  * which could be put in, for example, "/sbin/init.d/lan".
 1631  *
 1632  * Setting the variable is not necessary on HP-UX 11.x.
 1633  */
 1634 static int
 1635 get_dlpi_ppa(register int fd, register const char *device, register u_int unit,
 1636     u_int *ppa, register char *ebuf)
 1637 {
 1638     register dl_hp_ppa_ack_t *ap;
 1639     register dl_hp_ppa_info_t *ipstart, *ip;
 1640     register u_int i;
 1641     char dname[100];
 1642     register u_long majdev;
 1643     struct stat statbuf;
 1644     dl_hp_ppa_req_t req;
 1645     char buf[MAXDLBUF];
 1646     char *ppa_data_buf;
 1647     dl_hp_ppa_ack_t *dlp;
 1648     struct strbuf ctl;
 1649     int flags;
 1650 
 1651     memset((char *)&req, 0, sizeof(req));
 1652     req.dl_primitive = DL_HP_PPA_REQ;
 1653 
 1654     memset((char *)buf, 0, sizeof(buf));
 1655     if (send_request(fd, (char *)&req, sizeof(req), "hpppa", ebuf) < 0)
 1656         return (PCAP_ERROR);
 1657 
 1658     ctl.maxlen = DL_HP_PPA_ACK_SIZE;
 1659     ctl.len = 0;
 1660     ctl.buf = (char *)buf;
 1661 
 1662     flags = 0;
 1663     /*
 1664      * DLPI may return a big chunk of data for a DL_HP_PPA_REQ. The normal
 1665      * recv_ack will fail because it set the maxlen to MAXDLBUF (8192)
 1666      * which is NOT big enough for a DL_HP_PPA_REQ.
 1667      *
 1668      * This causes libpcap applications to fail on a system with HP-APA
 1669      * installed.
 1670      *
 1671      * To figure out how big the returned data is, we first call getmsg
 1672      * to get the small head and peek at the head to get the actual data
 1673      * length, and  then issue another getmsg to get the actual PPA data.
 1674      */
 1675     /* get the head first */
 1676     if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) {
 1677         pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
 1678             errno, "get_dlpi_ppa: hpppa getmsg");
 1679         return (PCAP_ERROR);
 1680     }
 1681     if (ctl.len == -1) {
 1682         snprintf(ebuf, PCAP_ERRBUF_SIZE,
 1683             "get_dlpi_ppa: hpppa getmsg: control buffer has no data");
 1684         return (PCAP_ERROR);
 1685     }
 1686 
 1687     dlp = (dl_hp_ppa_ack_t *)ctl.buf;
 1688     if (dlp->dl_primitive != DL_HP_PPA_ACK) {
 1689         snprintf(ebuf, PCAP_ERRBUF_SIZE,
 1690             "get_dlpi_ppa: hpppa unexpected primitive ack 0x%x",
 1691             (bpf_u_int32)dlp->dl_primitive);
 1692         return (PCAP_ERROR);
 1693     }
 1694 
 1695     if ((size_t)ctl.len < DL_HP_PPA_ACK_SIZE) {
 1696         snprintf(ebuf, PCAP_ERRBUF_SIZE,
 1697             "get_dlpi_ppa: hpppa ack too small (%d < %lu)",
 1698              ctl.len, (unsigned long)DL_HP_PPA_ACK_SIZE);
 1699         return (PCAP_ERROR);
 1700     }
 1701 
 1702     /* allocate buffer */
 1703     if ((ppa_data_buf = (char *)malloc(dlp->dl_length)) == NULL) {
 1704         pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
 1705             errno, "get_dlpi_ppa: hpppa malloc");
 1706         return (PCAP_ERROR);
 1707     }
 1708     ctl.maxlen = dlp->dl_length;
 1709     ctl.len = 0;
 1710     ctl.buf = (char *)ppa_data_buf;
 1711     /* get the data */
 1712     if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) {
 1713         pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
 1714             errno, "get_dlpi_ppa: hpppa getmsg");
 1715         free(ppa_data_buf);
 1716         return (PCAP_ERROR);
 1717     }
 1718     if (ctl.len == -1) {
 1719         snprintf(ebuf, PCAP_ERRBUF_SIZE,
 1720             "get_dlpi_ppa: hpppa getmsg: control buffer has no data");
 1721         return (PCAP_ERROR);
 1722     }
 1723     if ((u_int)ctl.len < dlp->dl_length) {
 1724         snprintf(ebuf, PCAP_ERRBUF_SIZE,
 1725             "get_dlpi_ppa: hpppa ack too small (%d < %lu)",
 1726             ctl.len, (unsigned long)dlp->dl_length);
 1727         free(ppa_data_buf);
 1728         return (PCAP_ERROR);
 1729     }
 1730 
 1731     ap = (dl_hp_ppa_ack_t *)buf;
 1732     ipstart = (dl_hp_ppa_info_t *)ppa_data_buf;
 1733     ip = ipstart;
 1734 
 1735 #ifdef HAVE_DL_HP_PPA_INFO_T_DL_MODULE_ID_1
 1736     /*
 1737      * The "dl_hp_ppa_info_t" structure has a "dl_module_id_1"
 1738      * member that should, in theory, contain the part of the
 1739      * name for the device that comes before the unit number,
 1740      * and should also have a "dl_module_id_2" member that may
 1741      * contain an alternate name (e.g., I think Ethernet devices
 1742      * have both "lan", for "lanN", and "snap", for "snapN", with
 1743      * the former being for Ethernet packets and the latter being
 1744      * for 802.3/802.2 packets).
 1745      *
 1746      * Search for the device that has the specified name and
 1747      * instance number.
 1748      */
 1749     for (i = 0; i < ap->dl_count; i++) {
 1750         if ((strcmp((const char *)ip->dl_module_id_1, device) == 0 ||
 1751              strcmp((const char *)ip->dl_module_id_2, device) == 0) &&
 1752             ip->dl_instance_num == unit)
 1753             break;
 1754 
 1755         ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset);
 1756     }
 1757 #else
 1758     /*
 1759      * We don't have that member, so the search is impossible; make it
 1760      * look as if the search failed.
 1761      */
 1762     i = ap->dl_count;
 1763 #endif
 1764 
 1765     if (i == ap->dl_count) {
 1766         /*
 1767          * Well, we didn't, or can't, find the device by name.
 1768          *
 1769          * HP-UX 10.20, whilst it has "dl_module_id_1" and
 1770          * "dl_module_id_2" fields in the "dl_hp_ppa_info_t",
 1771          * doesn't seem to fill them in unless the system is
 1772          * at a reasonably up-to-date patch level.
 1773          *
 1774          * Older HP-UX 10.x systems might not have those fields
 1775          * at all.
 1776          *
 1777          * Therefore, we'll search for the entry with the major
 1778          * device number of a device with the name "/dev/<dev><unit>",
 1779          * if such a device exists, as the old code did.
 1780          */
 1781         snprintf(dname, sizeof(dname), "/dev/%s%u", device, unit);
 1782         if (stat(dname, &statbuf) < 0) {
 1783             pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
 1784                 errno, "stat: %s", dname);
 1785             return (PCAP_ERROR);
 1786         }
 1787         majdev = major(statbuf.st_rdev);
 1788 
 1789         ip = ipstart;
 1790 
 1791         for (i = 0; i < ap->dl_count; i++) {
 1792             if (ip->dl_mjr_num == majdev &&
 1793                 ip->dl_instance_num == unit)
 1794                 break;
 1795 
 1796             ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset);
 1797         }
 1798     }
 1799     if (i == ap->dl_count) {
 1800         snprintf(ebuf, PCAP_ERRBUF_SIZE,
 1801             "can't find /dev/dlpi PPA for %s%u", device, unit);
 1802         return (PCAP_ERROR_NO_SUCH_DEVICE);
 1803     }
 1804     if (ip->dl_hdw_state == HDW_DEAD) {
 1805         snprintf(ebuf, PCAP_ERRBUF_SIZE,
 1806             "%s%d: hardware state: DOWN\n", device, unit);
 1807         free(ppa_data_buf);
 1808         return (PCAP_ERROR);
 1809     }
 1810     *ppa = ip->dl_ppa;
 1811     free(ppa_data_buf);
 1812     return (0);
 1813 }
 1814 #endif
 1815 
 1816 #ifdef HAVE_HPUX9
 1817 /*
 1818  * Under HP-UX 9, there is no good way to determine the ppa.
 1819  * So punt and read it from /dev/kmem.
 1820  */
 1821 static struct nlist nl[] = {
 1822 #define NL_IFNET 0
 1823     { "ifnet" },
 1824     { "" }
 1825 };
 1826 
 1827 static char path_vmunix[] = "/hp-ux";
 1828 
 1829 /* Determine ppa number that specifies ifname */
 1830 static int
 1831 get_dlpi_ppa(register int fd, register const char *ifname, register u_int unit,
 1832     u_int *ppa, register char *ebuf)
 1833 {
 1834     register const char *cp;
 1835     register int kd;
 1836     void *addr;
 1837     struct ifnet ifnet;
 1838     char if_name[sizeof(ifnet.if_name) + 1];
 1839 
 1840     cp = strrchr(ifname, '/');
 1841     if (cp != NULL)
 1842         ifname = cp + 1;
 1843     if (nlist(path_vmunix, &nl) < 0) {
 1844         snprintf(ebuf, PCAP_ERRBUF_SIZE, "nlist %s failed",
 1845             path_vmunix);
 1846         return (PCAP_ERROR);
 1847     }
 1848     if (nl[NL_IFNET].n_value == 0) {
 1849         snprintf(ebuf, PCAP_ERRBUF_SIZE,
 1850             "couldn't find %s kernel symbol",
 1851             nl[NL_IFNET].n_name);
 1852         return (PCAP_ERROR);
 1853     }
 1854     kd = open("/dev/kmem", O_RDONLY);
 1855     if (kd < 0) {
 1856         pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
 1857             errno, "kmem open");
 1858         return (PCAP_ERROR);
 1859     }
 1860     if (dlpi_kread(kd, nl[NL_IFNET].n_value,
 1861         &addr, sizeof(addr), ebuf) < 0) {
 1862         close(kd);
 1863         return (PCAP_ERROR);
 1864     }
 1865     for (; addr != NULL; addr = ifnet.if_next) {
 1866         if (dlpi_kread(kd, (off_t)addr,
 1867             &ifnet, sizeof(ifnet), ebuf) < 0 ||
 1868             dlpi_kread(kd, (off_t)ifnet.if_name,
 1869             if_name, sizeof(ifnet.if_name), ebuf) < 0) {
 1870             (void)close(kd);
 1871             return (PCAP_ERROR);
 1872         }
 1873         if_name[sizeof(ifnet.if_name)] = '\0';
 1874         if (strcmp(if_name, ifname) == 0 && ifnet.if_unit == unit) {
 1875             *ppa = ifnet.if_index;
 1876             return (0);
 1877         }
 1878     }
 1879 
 1880     snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't find %s", ifname);
 1881     return (PCAP_ERROR_NO_SUCH_DEVICE);
 1882 }
 1883 
 1884 static int
 1885 dlpi_kread(register int fd, register off_t addr,
 1886     register void *buf, register u_int len, register char *ebuf)
 1887 {
 1888     register int cc;
 1889 
 1890     if (lseek(fd, addr, SEEK_SET) < 0) {
 1891         pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
 1892             errno, "lseek");
 1893         return (-1);
 1894     }
 1895     cc = read(fd, buf, len);
 1896     if (cc < 0) {
 1897         pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
 1898             errno, "read");
 1899         return (-1);
 1900     } else if (cc != len) {
 1901         snprintf(ebuf, PCAP_ERRBUF_SIZE, "short read (%d != %d)", cc,
 1902             len);
 1903         return (-1);
 1904     }
 1905     return (cc);
 1906 }
 1907 #endif
 1908 
 1909 pcap_t *
 1910 pcapint_create_interface(const char *device _U_, char *ebuf)
 1911 {
 1912     pcap_t *p;
 1913 #ifdef DL_HP_RAWDLS
 1914     struct pcap_dlpi *pd;
 1915 #endif
 1916 
 1917     p = PCAP_CREATE_COMMON(ebuf, struct pcap_dlpi);
 1918     if (p == NULL)
 1919         return (NULL);
 1920 
 1921 #ifdef DL_HP_RAWDLS
 1922     pd = p->priv;
 1923     pd->send_fd = -1;   /* it hasn't been opened yet */
 1924 #endif
 1925 
 1926     p->activate_op = pcap_activate_dlpi;
 1927     return (p);
 1928 }
 1929 
 1930 /*
 1931  * Libpcap version string.
 1932  */
 1933 const char *
 1934 pcap_lib_version(void)
 1935 {
 1936     return (PCAP_VERSION_STRING);
 1937 }
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载