diff options
Diffstat (limited to 'pcap-dlpi.c')
-rw-r--r-- | pcap-dlpi.c | 570 |
1 files changed, 358 insertions, 212 deletions
diff --git a/pcap-dlpi.c b/pcap-dlpi.c index 4598600..3ed8fa7 100644 --- a/pcap-dlpi.c +++ b/pcap-dlpi.c @@ -69,7 +69,7 @@ */ #ifdef HAVE_CONFIG_H -#include "config.h" +#include <config.h> #endif #include <sys/types.h> @@ -122,18 +122,29 @@ #include "os-proto.h" #endif -#ifndef PCAP_DEV_PREFIX -#ifdef _AIX -#define PCAP_DEV_PREFIX "/dev/dlpi" -#else -#define PCAP_DEV_PREFIX "/dev" -#endif +#if defined(__hpux) + /* + * HP-UX has a /dev/dlpi device; you open it and set the PPA of the actual + * network device you want. + */ + #define HAVE_DEV_DLPI +#elif defined(_AIX) + /* + * AIX has a /dev/dlpi directory, with devices named after the interfaces + * underneath it. + */ + #define PCAP_DEV_PREFIX "/dev/dlpi" +#elif defined(HAVE_SOLARIS) + /* + * Solaris has devices named after the interfaces underneath /dev. + */ + #define PCAP_DEV_PREFIX "/dev" #endif #define MAXDLBUF 8192 /* Forwards */ -static char *split_dname(char *, int *, char *); +static char *split_dname(char *, u_int *, char *); static int dl_doattach(int, int, char *); #ifdef DL_HP_RAWDLS static int dl_dohpuxbind(int, char *); @@ -145,7 +156,7 @@ static int dlokack(int, const char *, char *, char *); static int dlinforeq(int, char *); static int dlinfoack(int, char *, char *); -#ifdef HAVE_DLPI_PASSIVE +#ifdef HAVE_DL_PASSIVE_REQ_T static void dlpassive(int, char *); #endif @@ -153,27 +164,21 @@ static void dlpassive(int, char *); static int dlrawdatareq(int, const u_char *, int); #endif static int recv_ack(int, int, const char *, char *, char *, int *); -static char *dlstrerror(bpf_u_int32); -static char *dlprim(bpf_u_int32); +static char *dlstrerror(char *, size_t, bpf_u_int32); +static char *dlprim(char *, size_t, bpf_u_int32); #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) -static char *get_release(bpf_u_int32 *, bpf_u_int32 *, bpf_u_int32 *); +#define GET_RELEASE_BUFSIZE 32 +static void get_release(char *, size_t, bpf_u_int32 *, bpf_u_int32 *, + bpf_u_int32 *); #endif static int send_request(int, char *, int, char *, char *); #ifdef HAVE_HPUX9 static int dlpi_kread(int, off_t, void *, u_int, char *); #endif #ifdef HAVE_DEV_DLPI -static int get_dlpi_ppa(int, const char *, int, char *); +static int get_dlpi_ppa(int, const char *, u_int, u_int *, char *); #endif -/* XXX Needed by HP-UX (at least) */ -static bpf_u_int32 ctlbuf[MAXDLBUF]; -static struct strbuf ctl = { - MAXDLBUF, - 0, - (char *)ctlbuf -}; - /* * Cast a buffer to "union DL_primitives" without provoking warnings * from the compiler. @@ -186,6 +191,12 @@ pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user) int cc; u_char *bp; int flags; + bpf_u_int32 ctlbuf[MAXDLBUF]; + struct strbuf ctl = { + MAXDLBUF, + 0, + (char *)ctlbuf + }; struct strbuf data; flags = 0; @@ -213,6 +224,9 @@ pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user) * would be DL_HP_RAWDATA_IND on HP-UX * if we're in raw mode? */ + ctl.buf = (char *)ctlbuf; + ctl.maxlen = MAXDLBUF; + ctl.len = 0; if (getmsg(p->fd, &ctl, &data, &flags) < 0) { /* Don't choke when we get ptraced */ switch (errno) { @@ -224,13 +238,13 @@ pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user) case EAGAIN: return (0); } - strlcpy(p->errbuf, pcap_strerror(errno), - sizeof(p->errbuf)); + pcap_fmt_errmsg_for_errno(p->errbuf, + sizeof(p->errbuf), errno, "getmsg"); return (-1); } cc = data.len; } while (cc == 0); - bp = p->buffer + p->offset; + bp = (u_char *)p->buffer + p->offset; } else bp = p->bp; @@ -248,20 +262,20 @@ pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size) #if defined(DLIOCRAW) ret = write(p->fd, buf, size); if (ret == -1) { - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s", - pcap_strerror(errno)); + pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + errno, "send"); return (-1); } #elif defined(DL_HP_RAWDLS) if (pd->send_fd < 0) { - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: Output FD couldn't be opened"); return (-1); } ret = dlrawdatareq(pd->send_fd, buf, size); if (ret == -1) { - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s", - pcap_strerror(errno)); + pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + errno, "send"); return (-1); } /* @@ -293,12 +307,12 @@ pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size) * it should check "p->linktype" and reject the send request if * it's anything other than DLT_EN10MB. */ - strlcpy(p->errbuf, "send: Not supported on this version of this OS", + pcap_strlcpy(p->errbuf, "send: Not supported on this version of this OS", PCAP_ERRBUF_SIZE); ret = -1; #endif /* raw mode */ return (ret); -} +} #ifndef DL_IPATM #define DL_IPATM 0x12 /* ATM Classical IP interface */ @@ -331,29 +345,15 @@ pcap_cleanup_dlpi(pcap_t *p) } static int -pcap_activate_dlpi(pcap_t *p) +open_dlpi_device(const char *name, u_int *ppa, char *errbuf) { -#ifdef DL_HP_RAWDLS - struct pcap_dlpi *pd = p->priv; -#endif - int status = 0; - int retv; - register char *cp; - int ppa; -#ifdef HAVE_SOLARIS - int isatm = 0; -#endif - register dl_info_ack_t *infop; -#ifdef HAVE_SYS_BUFMOD_H - bpf_u_int32 ss; -#ifdef HAVE_SOLARIS - register char *release; - bpf_u_int32 osmajor, osminor, osmicro; -#endif -#endif - bpf_u_int32 buf[MAXDLBUF]; + int status; char dname[100]; -#ifndef HAVE_DEV_DLPI + char *cp; + int fd; +#ifdef HAVE_DEV_DLPI + u_int unit; +#else char dname2[100]; #endif @@ -361,21 +361,19 @@ pcap_activate_dlpi(pcap_t *p) /* ** Remove any "/dev/" on the front of the device. */ - cp = strrchr(p->opt.source, '/'); + cp = strrchr(name, '/'); if (cp == NULL) - strlcpy(dname, p->opt.source, sizeof(dname)); + pcap_strlcpy(dname, name, sizeof(dname)); else - strlcpy(dname, cp + 1, sizeof(dname)); + pcap_strlcpy(dname, cp + 1, sizeof(dname)); /* * Split the device name into a device type name and a unit number; * chop off the unit number, so "dname" is just a device type name. */ - cp = split_dname(dname, &ppa, p->errbuf); - if (cp == NULL) { - status = PCAP_ERROR_NO_SUCH_DEVICE; - goto bad; - } + cp = split_dname(dname, &unit, errbuf); + if (cp == NULL) + return (PCAP_ERROR_NO_SUCH_DEVICE); *cp = '\0'; /* @@ -390,39 +388,24 @@ pcap_activate_dlpi(pcap_t *p) * device number, rather than hardwiring "/dev/dlpi". */ cp = "/dev/dlpi"; - if ((p->fd = open(cp, O_RDWR)) < 0) { + if ((fd = open(cp, O_RDWR)) < 0) { if (errno == EPERM || errno == EACCES) status = PCAP_ERROR_PERM_DENIED; else status = PCAP_ERROR; - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, - "%s: %s", cp, pcap_strerror(errno)); - goto bad; + pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, + errno, "%s", cp); + return (status); } -#ifdef DL_HP_RAWDLS - /* - * XXX - HP-UX 10.20 and 11.xx don't appear to support sending and - * receiving packets on the same descriptor - you need separate - * descriptors for sending and receiving, bound to different SAPs. - * - * If the open fails, we just leave -1 in "pd->send_fd" and reject - * attempts to send packets, just as if, in pcap-bpf.c, we fail - * to open the BPF device for reading and writing, we just try - * to open it for reading only and, if that succeeds, just let - * the send attempts fail. - */ - pd->send_fd = open(cp, O_RDWR); -#endif - /* * Get a table of all PPAs for that device, and search that * table for the specified device type name and unit number. */ - ppa = get_dlpi_ppa(p->fd, dname, ppa, p->errbuf); - if (ppa < 0) { - status = ppa; - goto bad; + status = get_dlpi_ppa(fd, dname, unit, ppa, errbuf); + if (status < 0) { + close(fd); + return (status); } #else /* @@ -431,43 +414,41 @@ pcap_activate_dlpi(pcap_t *p) * otherwise, concatenate the device directory name and the * device name. */ - if (*p->opt.source == '/') - strlcpy(dname, p->opt.source, sizeof(dname)); + if (*name == '/') + pcap_strlcpy(dname, name, sizeof(dname)); else - snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX, - p->opt.source); + pcap_snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX, + name); /* * Get the unit number, and a pointer to the end of the device * type name. */ - cp = split_dname(dname, &ppa, p->errbuf); - if (cp == NULL) { - status = PCAP_ERROR_NO_SUCH_DEVICE; - goto bad; - } + cp = split_dname(dname, ppa, errbuf); + if (cp == NULL) + return (PCAP_ERROR_NO_SUCH_DEVICE); /* * Make a copy of the device pathname, and then remove the unit * number from the device pathname. */ - strlcpy(dname2, dname, sizeof(dname)); + pcap_strlcpy(dname2, dname, sizeof(dname)); *cp = '\0'; /* Try device without unit number */ - if ((p->fd = open(dname, O_RDWR)) < 0) { + if ((fd = open(dname, O_RDWR)) < 0) { if (errno != ENOENT) { if (errno == EPERM || errno == EACCES) status = PCAP_ERROR_PERM_DENIED; else status = PCAP_ERROR; - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dname, - pcap_strerror(errno)); - goto bad; + pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, + errno, "%s", dname); + return (status); } /* Try again with unit number */ - if ((p->fd = open(dname2, O_RDWR)) < 0) { + if ((fd = open(dname2, O_RDWR)) < 0) { if (errno == ENOENT) { status = PCAP_ERROR_NO_SUCH_DEVICE; @@ -482,31 +463,78 @@ pcap_activate_dlpi(pcap_t *p) * found" with the device name, so people * don't get confused and think, for example, * that if they can't capture on "lo0" - * on Solaris the fix is to change libpcap - * (or the application that uses it) to - * look for something other than "/dev/lo0", - * as the fix is to look for an operating - * system other than Solaris - you just - * *can't* capture on a loopback interface - * on Solaris, the lack of a DLPI device - * for the loopback interface is just a - * symptom of that inability. + * on Solaris prior to Solaris 11 the fix + * is to change libpcap (or the application + * that uses it) to look for something other + * than "/dev/lo0", as the fix is to use + * Solaris 11 or some operating system + * other than Solaris - you just *can't* + * capture on a loopback interface + * on Solaris prior to Solaris 11, the lack + * of a DLPI device for the loopback + * interface is just a symptom of that + * inability. */ - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, - "%s: No DLPI device found", p->opt.source); + pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, + "%s: No DLPI device found", name); } else { if (errno == EPERM || errno == EACCES) status = PCAP_ERROR_PERM_DENIED; else status = PCAP_ERROR; - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", - dname2, pcap_strerror(errno)); + pcap_fmt_errmsg_for_errno(errbuf, + PCAP_ERRBUF_SIZE, errno, "%s", dname2); } - goto bad; + return (status); } /* XXX Assume unit zero */ - ppa = 0; + *ppa = 0; + } +#endif + return (fd); +} + +static int +pcap_activate_dlpi(pcap_t *p) +{ +#ifdef DL_HP_RAWDLS + struct pcap_dlpi *pd = p->priv; +#endif + int status = 0; + int retv; + u_int ppa; +#ifdef HAVE_SOLARIS + int isatm = 0; +#endif + register dl_info_ack_t *infop; +#ifdef HAVE_SYS_BUFMOD_H + bpf_u_int32 ss; +#ifdef HAVE_SOLARIS + char release[GET_RELEASE_BUFSIZE]; + bpf_u_int32 osmajor, osminor, osmicro; +#endif +#endif + bpf_u_int32 buf[MAXDLBUF]; + + p->fd = open_dlpi_device(p->opt.device, &ppa, p->errbuf); + if (p->fd < 0) { + status = p->fd; + goto bad; } + +#ifdef DL_HP_RAWDLS + /* + * XXX - HP-UX 10.20 and 11.xx don't appear to support sending and + * receiving packets on the same descriptor - you need separate + * descriptors for sending and receiving, bound to different SAPs. + * + * If the open fails, we just leave -1 in "pd->send_fd" and reject + * attempts to send packets, just as if, in pcap-bpf.c, we fail + * to open the BPF device for reading and writing, we just try + * to open it for reading only and, if that succeeds, just let + * the send attempts fail. + */ + pd->send_fd = open("/dev/dlpi", O_RDWR); #endif /* @@ -548,7 +576,7 @@ pcap_activate_dlpi(pcap_t *p) goto bad; } -#ifdef HAVE_DLPI_PASSIVE +#ifdef HAVE_DL_PASSIVE_REQ_T /* * Enable Passive mode to be able to capture on aggregated link. * Not supported in all Solaris versions. @@ -617,6 +645,17 @@ pcap_activate_dlpi(pcap_t *p) #endif /* AIX vs. HP-UX vs. other */ #endif /* !HP-UX 9 and !HP-UX 10.20 or later and !SINIX */ + /* + * Turn a negative snapshot value (invalid), a snapshot value of + * 0 (unspecified), or a value bigger than the normal maximum + * value, into the maximum allowed value. + * + * If some application really *needs* a bigger snapshot + * length, we should just increase MAXIMUM_SNAPLEN. + */ + if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN) + p->snapshot = MAXIMUM_SNAPLEN; + #ifdef HAVE_SOLARIS if (isatm) { /* @@ -627,8 +666,8 @@ pcap_activate_dlpi(pcap_t *p) */ if (strioctl(p->fd, A_PROMISCON_REQ, 0, NULL) < 0) { status = PCAP_ERROR; - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, - "A_PROMISCON_REQ: %s", pcap_strerror(errno)); + pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + errno, "A_PROMISCON_REQ"); goto bad; } } else @@ -745,8 +784,8 @@ pcap_activate_dlpi(pcap_t *p) */ if (strioctl(p->fd, DLIOCRAW, 0, NULL) < 0) { status = PCAP_ERROR; - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "DLIOCRAW: %s", - pcap_strerror(errno)); + pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + errno, "DLIOCRAW"); goto bad; } #endif @@ -763,10 +802,10 @@ pcap_activate_dlpi(pcap_t *p) ** Ask for bugid 1149065. */ #ifdef HAVE_SOLARIS - release = get_release(&osmajor, &osminor, &osmicro); + get_release(release, sizeof (release), &osmajor, &osminor, &osmicro); if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) && getenv("BUFMOD_FIXED") == NULL) { - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "WARNING: bufmod is broken in SunOS %s; ignoring snaplen.", release); ss = 0; @@ -786,8 +825,8 @@ pcap_activate_dlpi(pcap_t *p) */ if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) { status = PCAP_ERROR; - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s", - pcap_strerror(errno)); + pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + errno, "FLUSHR"); goto bad; } @@ -830,7 +869,7 @@ bad: * Returns NULL on error, and fills "ebuf" with an error message. */ static char * -split_dname(char *device, int *unitp, char *ebuf) +split_dname(char *device, u_int *unitp, char *ebuf) { char *cp; char *eos; @@ -841,7 +880,7 @@ split_dname(char *device, int *unitp, char *ebuf) */ cp = device + strlen(device) - 1; if (*cp < '0' || *cp > '9') { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s missing unit number", + pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s missing unit number", device); return (NULL); } @@ -853,20 +892,20 @@ split_dname(char *device, int *unitp, char *ebuf) errno = 0; unit = strtol(cp, &eos, 10); if (*eos != '\0') { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s bad unit number", device); + pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s bad unit number", device); return (NULL); } if (errno == ERANGE || unit > INT_MAX) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number too large", + pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number too large", device); return (NULL); } if (unit < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number is negative", + pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number is negative", device); return (NULL); } - *unitp = (int)unit; + *unitp = (u_int)unit; return (cp); } @@ -929,7 +968,7 @@ dl_dohpuxbind(int fd, char *ebuf) *ebuf = '\0'; hpsap++; if (hpsap > 100) { - strlcpy(ebuf, + pcap_strlcpy(ebuf, "All SAPs from 22 through 100 are in use", PCAP_ERRBUF_SIZE); return (-1); @@ -960,8 +999,81 @@ dlpromiscon(pcap_t *p, bpf_u_int32 level) return (0); } +/* + * Not all interfaces are DLPI interfaces, and thus not all interfaces + * can be opened with DLPI (for example, the loopback interface is not + * a DLPI interface on Solaris prior to Solaris 11), so try to open + * the specified interface; return 0 if we fail with PCAP_ERROR_NO_SUCH_DEVICE + * and 1 otherwise. + */ +static int +is_dlpi_interface(const char *name) +{ + int fd; + u_int ppa; + char errbuf[PCAP_ERRBUF_SIZE]; + + fd = open_dlpi_device(name, &ppa, errbuf); + if (fd < 0) { + /* + * Error - was it PCAP_ERROR_NO_SUCH_DEVICE? + */ + if (fd == PCAP_ERROR_NO_SUCH_DEVICE) { + /* + * Yes, so we can't open this because it's + * not a DLPI interface. + */ + return (0); + } + /* + * No, so, in the case where there's a single DLPI + * device for all interfaces of this type ("style + * 2" providers?), we don't know whether it's a DLPI + * interface or not, as we didn't try an attach. + * Say it is a DLPI device, so that the user can at + * least try to open it and report the error (which + * is probably "you don't have permission to open that + * DLPI device"; reporting those interfaces means + * users will ask "why am I getting a permissions error + * when I try to capture" rather than "why am I not + * seeing any interfaces", making the underlying problem + * clearer). + */ + return (1); + } + + /* + * Success. + */ + close(fd); + return (1); +} + +static int +get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_) +{ + /* + * Nothing we can do other than mark loopback devices as "the + * connected/disconnected status doesn't apply". + * + * XXX - on Solaris, can we do what the dladm command does, + * i.e. get a connected/disconnected indication from a kstat? + * (Note that you can also get the link speed, and possibly + * other information, from a kstat as well.) + */ + if (*flags & PCAP_IF_LOOPBACK) { + /* + * Loopback devices aren't wireless, and "connected"/ + * "disconnected" doesn't apply to them. + */ + *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE; + return (0); + } + return (0); +} + int -pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) +pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf) { #ifdef HAVE_SOLARIS int fd; @@ -972,7 +1084,16 @@ pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) } buf; char baname[2+1+1]; u_int i; +#endif + + /* + * Get the list of regular interfaces first. + */ + if (pcap_findalldevs_interfaces(devlistp, errbuf, is_dlpi_interface, + get_if_flags) == -1) + return (-1); /* failure */ +#ifdef HAVE_SOLARIS /* * We may have to do special magic to get ATM devices. */ @@ -989,13 +1110,18 @@ pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) } if (strioctl(fd, A_GET_UNITS, sizeof(buf), (char *)&buf) < 0) { - snprintf(errbuf, PCAP_ERRBUF_SIZE, "A_GET_UNITS: %s", - pcap_strerror(errno)); + pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, + errno, "A_GET_UNITS"); return (-1); } for (i = 0; i < buf.nunits; i++) { - snprintf(baname, sizeof baname, "ba%u", i); - if (pcap_add_if(alldevsp, baname, 0, NULL, errbuf) < 0) + pcap_snprintf(baname, sizeof baname, "ba%u", i); + /* + * XXX - is there a notion of "up" and "running"? + * And is there a way to determine whether the + * interface is plugged into a network? + */ + if (add_dev(devlistp, baname, 0, NULL, errbuf) == NULL) return (-1); } #endif @@ -1015,9 +1141,8 @@ send_request(int fd, char *ptr, int len, char *what, char *ebuf) flags = 0; if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, - "send_request: putmsg \"%s\": %s", - what, pcap_strerror(errno)); + pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, + errno, "send_request: putmsg \"%s\"", what); return (-1); } return (0); @@ -1029,6 +1154,8 @@ recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror union DL_primitives *dlp; struct strbuf ctl; int flags; + char errmsgbuf[PCAP_ERRBUF_SIZE]; + char dlprimbuf[64]; /* * Clear out "*uerror", so it's only set for DL_ERROR_ACK/DL_SYSERR, @@ -1043,8 +1170,8 @@ recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror flags = 0; if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s getmsg: %s", - what, pcap_strerror(errno)); + pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, + errno, "recv_ack: %s getmsg", what); return (PCAP_ERROR); } @@ -1066,17 +1193,18 @@ recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror case DL_SYSERR: if (uerror != NULL) *uerror = dlp->error_ack.dl_unix_errno; - snprintf(ebuf, PCAP_ERRBUF_SIZE, - "recv_ack: %s: UNIX error - %s", - what, pcap_strerror(dlp->error_ack.dl_unix_errno)); + pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, + dlp->error_ack.dl_unix_errno, + "recv_ack: %s: UNIX error", what); if (dlp->error_ack.dl_unix_errno == EPERM || dlp->error_ack.dl_unix_errno == EACCES) return (PCAP_ERROR_PERM_DENIED); break; default: - snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: %s", - what, dlstrerror(dlp->error_ack.dl_errno)); + pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, + "recv_ack: %s: %s", what, + dlstrerror(errmsgbuf, sizeof (errmsgbuf), dlp->error_ack.dl_errno)); if (dlp->error_ack.dl_errno == DL_BADPPA) return (PCAP_ERROR_NO_SUCH_DEVICE); else if (dlp->error_ack.dl_errno == DL_ACCESS) @@ -1086,14 +1214,14 @@ recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror return (PCAP_ERROR); default: - snprintf(ebuf, PCAP_ERRBUF_SIZE, + pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: Unexpected primitive ack %s", - what, dlprim(dlp->dl_primitive)); + what, dlprim(dlprimbuf, sizeof (dlprimbuf), dlp->dl_primitive)); return (PCAP_ERROR); } if (ctl.len < size) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, + pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: Ack too small (%d < %d)", what, ctl.len, size); return (PCAP_ERROR); @@ -1102,10 +1230,8 @@ recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror } static char * -dlstrerror(bpf_u_int32 dl_errno) +dlstrerror(char *errbuf, size_t errbufsize, bpf_u_int32 dl_errno) { - static char errstring[6+2+8+1]; - switch (dl_errno) { case DL_ACCESS: @@ -1206,16 +1332,14 @@ dlstrerror(bpf_u_int32 dl_errno) return ("Pending outstanding connect indications"); default: - sprintf(errstring, "Error %02x", dl_errno); - return (errstring); + pcap_snprintf(errbuf, errbufsize, "Error %02x", dl_errno); + return (errbuf); } } static char * -dlprim(bpf_u_int32 prim) +dlprim(char *primbuf, size_t primbufsize, bpf_u_int32 prim) { - static char primbuf[80]; - switch (prim) { case DL_INFO_REQ: @@ -1300,7 +1424,8 @@ dlprim(bpf_u_int32 prim) return ("DL_RESET_CON"); default: - (void) sprintf(primbuf, "unknown primitive 0x%x", prim); + pcap_snprintf(primbuf, primbufsize, "unknown primitive 0x%x", + prim); return (primbuf); } } @@ -1357,7 +1482,7 @@ dlinfoack(int fd, char *bufp, char *ebuf) return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf, NULL)); } -#ifdef HAVE_DLPI_PASSIVE +#ifdef HAVE_DL_PASSIVE_REQ_T /* * Enable DLPI passive mode. We do not care if this request fails, as this * indicates the underlying DLPI device does not support link aggregation. @@ -1412,28 +1537,29 @@ dlrawdatareq(int fd, const u_char *datap, int datalen) #endif /* DL_HP_RAWDLS */ #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) -static char * -get_release(bpf_u_int32 *majorp, bpf_u_int32 *minorp, bpf_u_int32 *microp) +static void +get_release(char *buf, size_t bufsize, bpf_u_int32 *majorp, + bpf_u_int32 *minorp, bpf_u_int32 *microp) { char *cp; - static char buf[32]; *majorp = 0; *minorp = 0; *microp = 0; - if (sysinfo(SI_RELEASE, buf, sizeof(buf)) < 0) - return ("?"); + if (sysinfo(SI_RELEASE, buf, bufsize) < 0) { + pcap_strlcpy(buf, "?", bufsize); + return; + } cp = buf; if (!isdigit((unsigned char)*cp)) - return (buf); + return; *majorp = strtol(cp, &cp, 10); if (*cp++ != '.') - return (buf); + return; *minorp = strtol(cp, &cp, 10); if (*cp++ != '.') - return (buf); + return; *microp = strtol(cp, &cp, 10); - return (buf); } #endif @@ -1478,12 +1604,12 @@ echo 'lanc_outbound_promisc_flag/W1' | /usr/bin/adb -w /stand/vmunix /dev/kmem * Setting the variable is not necessary on HP-UX 11.x. */ static int -get_dlpi_ppa(register int fd, register const char *device, register int unit, - register char *ebuf) +get_dlpi_ppa(register int fd, register const char *device, register u_int unit, + u_int *ppa, register char *ebuf) { register dl_hp_ppa_ack_t *ap; register dl_hp_ppa_info_t *ipstart, *ip; - register int i; + register u_int i; char dname[100]; register u_long majdev; struct stat statbuf; @@ -1493,7 +1619,6 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit, dl_hp_ppa_ack_t *dlp; struct strbuf ctl; int flags; - int ppa; memset((char *)&req, 0, sizeof(req)); req.dl_primitive = DL_HP_PPA_REQ; @@ -1521,21 +1646,26 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit, */ /* get the head first */ if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, - "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno)); + pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, + errno, "get_dlpi_ppa: hpppa getmsg"); + return (PCAP_ERROR); + } + if (ctl.len == -1) { + pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, + "get_dlpi_ppa: hpppa getmsg: control buffer has no data"); return (PCAP_ERROR); } dlp = (dl_hp_ppa_ack_t *)ctl.buf; if (dlp->dl_primitive != DL_HP_PPA_ACK) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, + pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "get_dlpi_ppa: hpppa unexpected primitive ack 0x%x", (bpf_u_int32)dlp->dl_primitive); return (PCAP_ERROR); } - if (ctl.len < DL_HP_PPA_ACK_SIZE) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, + if ((size_t)ctl.len < DL_HP_PPA_ACK_SIZE) { + pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "get_dlpi_ppa: hpppa ack too small (%d < %lu)", ctl.len, (unsigned long)DL_HP_PPA_ACK_SIZE); return (PCAP_ERROR); @@ -1543,8 +1673,8 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit, /* allocate buffer */ if ((ppa_data_buf = (char *)malloc(dlp->dl_length)) == NULL) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, - "get_dlpi_ppa: hpppa malloc: %s", pcap_strerror(errno)); + pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, + errno, "get_dlpi_ppa: hpppa malloc"); return (PCAP_ERROR); } ctl.maxlen = dlp->dl_length; @@ -1552,13 +1682,18 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit, ctl.buf = (char *)ppa_data_buf; /* get the data */ if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, - "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno)); + pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, + errno, "get_dlpi_ppa: hpppa getmsg"); free(ppa_data_buf); return (PCAP_ERROR); } - if (ctl.len < dlp->dl_length) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, + if (ctl.len == -1) { + pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, + "get_dlpi_ppa: hpppa getmsg: control buffer has no data"); + return (PCAP_ERROR); + } + if ((u_int)ctl.len < dlp->dl_length) { + pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "get_dlpi_ppa: hpppa ack too small (%d < %lu)", ctl.len, (unsigned long)dlp->dl_length); free(ppa_data_buf); @@ -1569,7 +1704,7 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit, ipstart = (dl_hp_ppa_info_t *)ppa_data_buf; ip = ipstart; -#ifdef HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1 +#ifdef HAVE_DL_HP_PPA_INFO_T_DL_MODULE_ID_1 /* * The "dl_hp_ppa_info_t" structure has a "dl_module_id_1" * member that should, in theory, contain the part of the @@ -1615,10 +1750,10 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit, * device number of a device with the name "/dev/<dev><unit>", * if such a device exists, as the old code did. */ - snprintf(dname, sizeof(dname), "/dev/%s%d", device, unit); + pcap_snprintf(dname, sizeof(dname), "/dev/%s%u", device, unit); if (stat(dname, &statbuf) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "stat: %s: %s", - dname, pcap_strerror(errno)); + pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, + errno, "stat: %s", dname); return (PCAP_ERROR); } majdev = major(statbuf.st_rdev); @@ -1634,19 +1769,19 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit, } } if (i == ap->dl_count) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, - "can't find /dev/dlpi PPA for %s%d", device, unit); + pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, + "can't find /dev/dlpi PPA for %s%u", device, unit); return (PCAP_ERROR_NO_SUCH_DEVICE); } if (ip->dl_hdw_state == HDW_DEAD) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, + pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s%d: hardware state: DOWN\n", device, unit); free(ppa_data_buf); return (PCAP_ERROR); } - ppa = ip->dl_ppa; + *ppa = ip->dl_ppa; free(ppa_data_buf); - return (ppa); + return (0); } #endif @@ -1665,8 +1800,8 @@ static char path_vmunix[] = "/hp-ux"; /* Determine ppa number that specifies ifname */ static int -get_dlpi_ppa(register int fd, register const char *ifname, register int unit, - register char *ebuf) +get_dlpi_ppa(register int fd, register const char *ifname, register u_int unit, + u_int *ppa, register char *ebuf) { register const char *cp; register int kd; @@ -1678,26 +1813,26 @@ get_dlpi_ppa(register int fd, register const char *ifname, register int unit, if (cp != NULL) ifname = cp + 1; if (nlist(path_vmunix, &nl) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "nlist %s failed", + pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "nlist %s failed", path_vmunix); - return (-1); + return (PCAP_ERROR); } if (nl[NL_IFNET].n_value == 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, + pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "could't find %s kernel symbol", nl[NL_IFNET].n_name); - return (-1); + return (PCAP_ERROR); } kd = open("/dev/kmem", O_RDONLY); if (kd < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "kmem open: %s", - pcap_strerror(errno)); - return (-1); + pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, + errno, "kmem open"); + return (PCAP_ERROR); } if (dlpi_kread(kd, nl[NL_IFNET].n_value, &addr, sizeof(addr), ebuf) < 0) { close(kd); - return (-1); + return (PCAP_ERROR); } for (; addr != NULL; addr = ifnet.if_next) { if (dlpi_kread(kd, (off_t)addr, @@ -1705,15 +1840,17 @@ get_dlpi_ppa(register int fd, register const char *ifname, register int unit, dlpi_kread(kd, (off_t)ifnet.if_name, if_name, sizeof(ifnet.if_name), ebuf) < 0) { (void)close(kd); - return (-1); + return (PCAP_ERROR); } if_name[sizeof(ifnet.if_name)] = '\0'; - if (strcmp(if_name, ifname) == 0 && ifnet.if_unit == unit) - return (ifnet.if_index); + if (strcmp(if_name, ifname) == 0 && ifnet.if_unit == unit) { + *ppa = ifnet.if_index; + return (0); + } } - snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't find %s", ifname); - return (-1); + pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't find %s", ifname); + return (PCAP_ERROR_NO_SUCH_DEVICE); } static int @@ -1723,17 +1860,17 @@ dlpi_kread(register int fd, register off_t addr, register int cc; if (lseek(fd, addr, SEEK_SET) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "lseek: %s", - pcap_strerror(errno)); + pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, + errno, "lseek"); return (-1); } cc = read(fd, buf, len); if (cc < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "read: %s", - pcap_strerror(errno)); + pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, + errno, "read"); return (-1); } else if (cc != len) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "short read (%d != %d)", cc, + pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "short read (%d != %d)", cc, len); return (-1); } @@ -1742,14 +1879,14 @@ dlpi_kread(register int fd, register off_t addr, #endif pcap_t * -pcap_create_interface(const char *device, char *ebuf) +pcap_create_interface(const char *device _U_, char *ebuf) { pcap_t *p; #ifdef DL_HP_RAWDLS struct pcap_dlpi *pd; #endif - p = pcap_create_common(device, ebuf, sizeof (struct pcap_dlpi)); + p = pcap_create_common(ebuf, sizeof (struct pcap_dlpi)); if (p == NULL) return (NULL); @@ -1761,3 +1898,12 @@ pcap_create_interface(const char *device, char *ebuf) p->activate_op = pcap_activate_dlpi; return (p); } + +/* + * Libpcap version string. + */ +const char * +pcap_lib_version(void) +{ + return (PCAP_VERSION_STRING); +} |