📄 pcap-dlpi.c
字号:
default: (void) sprintf(primbuf, "unknown primitive 0x%x", prim); return (primbuf); }}static intdlattachreq(int fd, bpf_u_int32 ppa, char *ebuf){ dl_attach_req_t req; req.dl_primitive = DL_ATTACH_REQ; req.dl_ppa = ppa; return (send_request(fd, (char *)&req, sizeof(req), "attach", ebuf));}static intdlbindreq(int fd, bpf_u_int32 sap, char *ebuf){ dl_bind_req_t req; memset((char *)&req, 0, sizeof(req)); req.dl_primitive = DL_BIND_REQ; /* XXX - what if neither of these are defined? */#if defined(DL_HP_RAWDLS) req.dl_max_conind = 1; /* XXX magic number */ req.dl_service_mode = DL_HP_RAWDLS;#elif defined(DL_CLDLS) req.dl_service_mode = DL_CLDLS;#endif req.dl_sap = sap; return (send_request(fd, (char *)&req, sizeof(req), "bind", ebuf));}static intdlbindack(int fd, char *bufp, char *ebuf, int *uerror){ return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf, uerror));}static intdlpromisconreq(int fd, bpf_u_int32 level, char *ebuf){ dl_promiscon_req_t req; req.dl_primitive = DL_PROMISCON_REQ; req.dl_level = level; return (send_request(fd, (char *)&req, sizeof(req), "promiscon", ebuf));}static intdlokack(int fd, const char *what, char *bufp, char *ebuf){ return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf, NULL));}static intdlinforeq(int fd, char *ebuf){ dl_info_req_t req; req.dl_primitive = DL_INFO_REQ; return (send_request(fd, (char *)&req, sizeof(req), "info", ebuf));}static intdlinfoack(int fd, char *bufp, char *ebuf){ return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf, NULL));}#ifdef DL_HP_RAWDLS/* * There's an ack *if* there's an error. */static intdlrawdatareq(int fd, const u_char *datap, int datalen){ struct strbuf ctl, data; long buf[MAXDLBUF]; /* XXX - char? */ union DL_primitives *dlp; int dlen; dlp = (union DL_primitives*) buf; dlp->dl_primitive = DL_HP_RAWDATA_REQ; dlen = DL_HP_RAWDATA_REQ_SIZE; /* * HP's documentation doesn't appear to show us supplying any * address pointed to by the control part of the message. * I think that's what raw mode means - you just send the raw * packet, you don't specify where to send it to, as that's * implied by the destination address. */ ctl.maxlen = 0; ctl.len = dlen; ctl.buf = (void *)buf; data.maxlen = 0; data.len = datalen; data.buf = (void *)datap; return (putmsg(fd, &ctl, &data, 0));}#endif /* DL_HP_RAWDLS */#ifdef HAVE_SYS_BUFMOD_Hstatic intstrioctl(int fd, int cmd, int len, char *dp){ struct strioctl str; int rc; str.ic_cmd = cmd; str.ic_timout = -1; str.ic_len = len; str.ic_dp = dp; rc = ioctl(fd, I_STR, &str); if (rc < 0) return (rc); else return (str.ic_len);}#endif#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){ char *cp; static char buf[32]; *majorp = 0; *minorp = 0; *microp = 0; if (sysinfo(SI_RELEASE, buf, sizeof(buf)) < 0) return ("?"); cp = buf; if (!isdigit((unsigned char)*cp)) return (buf); *majorp = strtol(cp, &cp, 10); if (*cp++ != '.') return (buf); *minorp = strtol(cp, &cp, 10); if (*cp++ != '.') return (buf); *microp = strtol(cp, &cp, 10); return (buf);}#endif#ifdef DL_HP_PPA_REQ/* * Under HP-UX 10 and HP-UX 11, we can ask for the ppa *//* * Determine ppa number that specifies ifname. * * If the "dl_hp_ppa_info_t" doesn't have a "dl_module_id_1" member, * the code that's used here is the old code for HP-UX 10.x. * * However, HP-UX 10.20, at least, appears to have such a member * in its "dl_hp_ppa_info_t" structure, so the new code is used. * The new code didn't work on an old 10.20 system on which Rick * Jones of HP tried it, but with later patches installed, it * worked - it appears that the older system had those members but * didn't put anything in them, so, if the search by name fails, we * do the old search. * * Rick suggests that making sure your system is "up on the latest * lancommon/DLPI/driver patches" is probably a good idea; it'd fix * that problem, as well as allowing libpcap to see packets sent * from the system on which the libpcap application is being run. * (On 10.20, in addition to getting the latest patches, you need * to turn the kernel "lanc_outbound_promisc_flag" flag on with ADB; * a posting to "comp.sys.hp.hpux" at * * http://www.deja.com/[ST_rn=ps]/getdoc.xp?AN=558092266 * * says that, to see the machine's outgoing traffic, you'd need to * apply the right patches to your system, and also set that variable * with:echo 'lanc_outbound_promisc_flag/W1' | /usr/bin/adb -w /stand/vmunix /dev/kmem * which could be put in, for example, "/sbin/init.d/lan". * * Setting the variable is not necessary on HP-UX 11.x. */static intget_dlpi_ppa(register int fd, register const char *device, register int unit, register char *ebuf){ register dl_hp_ppa_ack_t *ap; register dl_hp_ppa_info_t *ipstart, *ip; register int i; char dname[100]; register u_long majdev; struct stat statbuf; dl_hp_ppa_req_t req; char buf[MAXDLBUF]; char *ppa_data_buf; 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; memset((char *)buf, 0, sizeof(buf)); if (send_request(fd, (char *)&req, sizeof(req), "hpppa", ebuf) < 0) return (-1); ctl.maxlen = DL_HP_PPA_ACK_SIZE; ctl.len = 0; ctl.buf = (char *)buf; flags = 0; /* * DLPI may return a big chunk of data for a DL_HP_PPA_REQ. The normal * recv_ack will fail because it set the maxlen to MAXDLBUF (8192) * which is NOT big enough for a DL_HP_PPA_REQ. * * This causes libpcap applications to fail on a system with HP-APA * installed. * * To figure out how big the returned data is, we first call getmsg * to get the small head and peek at the head to get the actual data * length, and then issue another getmsg to get the actual PPA data. */ /* 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)); return (-1); } dlp = (dl_hp_ppa_ack_t *)ctl.buf; if (dlp->dl_primitive != DL_HP_PPA_ACK) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "get_dlpi_ppa: hpppa unexpected primitive ack 0x%x", (bpf_u_int32)dlp->dl_primitive); return (-1); } if (ctl.len < DL_HP_PPA_ACK_SIZE) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "get_dlpi_ppa: hpppa ack too small (%d < %lu)", ctl.len, (unsigned long)DL_HP_PPA_ACK_SIZE); return (-1); } /* 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)); return (-1); } ctl.maxlen = dlp->dl_length; ctl.len = 0; 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)); free(ppa_data_buf); return (-1); } if (ctl.len < dlp->dl_length) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "get_dlpi_ppa: hpppa ack too small (%d < %d)", ctl.len, dlp->dl_length); free(ppa_data_buf); return (-1); } ap = (dl_hp_ppa_ack_t *)buf; ipstart = (dl_hp_ppa_info_t *)ppa_data_buf; ip = ipstart;#ifdef HAVE_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 * name for the device that comes before the unit number, * and should also have a "dl_module_id_2" member that may * contain an alternate name (e.g., I think Ethernet devices * have both "lan", for "lanN", and "snap", for "snapN", with * the former being for Ethernet packets and the latter being * for 802.3/802.2 packets). * * Search for the device that has the specified name and * instance number. */ for (i = 0; i < ap->dl_count; i++) { if ((strcmp((const char *)ip->dl_module_id_1, device) == 0 || strcmp((const char *)ip->dl_module_id_2, device) == 0) && ip->dl_instance_num == unit) break; ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset); }#else /* * We don't have that member, so the search is impossible; make it * look as if the search failed. */ i = ap->dl_count;#endif if (i == ap->dl_count) { /* * Well, we didn't, or can't, find the device by name. * * HP-UX 10.20, whilst it has "dl_module_id_1" and * "dl_module_id_2" fields in the "dl_hp_ppa_info_t", * doesn't seem to fill them in unless the system is * at a reasonably up-to-date patch level. * * Older HP-UX 10.x systems might not have those fields * at all. * * Therefore, we'll search for the entry with the major * 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); if (stat(dname, &statbuf) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "stat: %s: %s", dname, pcap_strerror(errno)); return (-1); } majdev = major(statbuf.st_rdev); ip = ipstart; for (i = 0; i < ap->dl_count; i++) { if (ip->dl_mjr_num == majdev && ip->dl_instance_num == unit) break; ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset); } } if (i == ap->dl_count) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "can't find /dev/dlpi PPA for %s%d", device, unit); return (-1); } if (ip->dl_hdw_state == HDW_DEAD) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s%d: hardware state: DOWN\n", device, unit); free(ppa_data_buf); return (-1); } ppa = ip->dl_ppa; free(ppa_data_buf); return (ppa);}#endif#ifdef HAVE_HPUX9/* * Under HP-UX 9, there is no good way to determine the ppa. * So punt and read it from /dev/kmem. */static struct nlist nl[] = {#define NL_IFNET 0 { "ifnet" }, { "" }};static char path_vmunix[] = "/hp-ux";/* Determine ppa number that specifies ifname */static intget_dlpi_ppa(register int fd, register const char *ifname, register int unit, register char *ebuf){ register const char *cp; register int kd; void *addr; struct ifnet ifnet; char if_name[sizeof(ifnet.if_name) + 1]; cp = strrchr(ifname, '/'); if (cp != NULL) ifname = cp + 1; if (nlist(path_vmunix, &nl) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "nlist %s failed", path_vmunix); return (-1); } if (nl[NL_IFNET].n_value == 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "could't find %s kernel symbol", nl[NL_IFNET].n_name); return (-1); } kd = open("/dev/kmem", O_RDONLY); if (kd < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "kmem open: %s", pcap_strerror(errno)); return (-1); } if (dlpi_kread(kd, nl[NL_IFNET].n_value, &addr, sizeof(addr), ebuf) < 0) { close(kd); return (-1); } for (; addr != NULL; addr = ifnet.if_next) { if (dlpi_kread(kd, (off_t)addr, &ifnet, sizeof(ifnet), ebuf) < 0 || dlpi_kread(kd, (off_t)ifnet.if_name, if_name, sizeof(ifnet.if_name), ebuf) < 0) { (void)close(kd); return (-1); } if_name[sizeof(ifnet.if_name)] = '\0'; if (strcmp(if_name, ifname) == 0 && ifnet.if_unit == unit) return (ifnet.if_index); } snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't find %s", ifname); return (-1);}static intdlpi_kread(register int fd, register off_t addr, register void *buf, register u_int len, register char *ebuf){ register int cc; if (lseek(fd, addr, SEEK_SET) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "lseek: %s", pcap_strerror(errno)); return (-1); } cc = read(fd, buf, len); if (cc < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "read: %s", pcap_strerror(errno)); return (-1); } else if (cc != len) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "short read (%d != %d)", cc, len); return (-1); } return (cc);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -