📄 pcap-dlpi.c
字号:
p->selectable_fd = p->fd; p->read_op = pcap_read_dlpi; p->inject_op = pcap_inject_dlpi; p->setfilter_op = install_bpf_program; /* no kernel filtering */ p->setdirection_op = NULL; /* Not implemented.*/ p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_stats_dlpi; p->close_op = pcap_close_dlpi; return (p);bad: if (p->fd >= 0) close(p->fd); if (p->send_fd >= 0) close(p->send_fd); /* * Get rid of any link-layer type list we allocated. */ if (p->dlt_list != NULL) free(p->dlt_list); free(p); return (NULL);}/* * Split a device name into a device type name and a unit number; * return the a pointer to the beginning of the unit number, which * is the end of the device type name, and set "*unitp" to the unit * number. * * Returns NULL on error, and fills "ebuf" with an error message. */static char *split_dname(char *device, int *unitp, char *ebuf){ char *cp; char *eos; long unit; /* * Look for a number at the end of the device name string. */ cp = device + strlen(device) - 1; if (*cp < '0' || *cp > '9') { snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s missing unit number", device); return (NULL); } /* Digits at end of string are unit number */ while (cp-1 >= device && *(cp-1) >= '0' && *(cp-1) <= '9') cp--; errno = 0; unit = strtol(cp, &eos, 10); if (*eos != '\0') { 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", device); return (NULL); } if (unit < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number is negative", device); return (NULL); } *unitp = (int)unit; return (cp);}static intdl_doattach(int fd, int ppa, char *ebuf){ bpf_u_int32 buf[MAXDLBUF]; if (dlattachreq(fd, ppa, ebuf) < 0 || dlokack(fd, "attach", (char *)buf, ebuf) < 0) return (-1); return (0);}#ifdef DL_HP_RAWDLSstatic intdl_dohpuxbind(int fd, char *ebuf){ int hpsap; int uerror; bpf_u_int32 buf[MAXDLBUF]; /* * XXX - we start at 22 because we used to use only 22, but * that was just because that was the value used in some * sample code from HP. With what value *should* we start? * Does it matter, given that we're enabling SAP promiscuity * on the input FD? */ hpsap = 22; for (;;) { if (dlbindreq(fd, hpsap, ebuf) < 0) return (-1); if (dlbindack(fd, (char *)buf, ebuf, &uerror) >= 0) break; /* * For any error other than a UNIX EBUSY, give up. */ if (uerror != EBUSY) { /* * dlbindack() has already filled in ebuf for * this error. */ return (-1); } /* * For EBUSY, try the next SAP value; that means that * somebody else is using that SAP. Clear ebuf so * that application doesn't report the "Device busy" * error as a warning. */ *ebuf = '\0'; hpsap++; if (hpsap > 100) { strlcpy(ebuf, "All SAPs from 22 through 100 are in use", PCAP_ERRBUF_SIZE); return (-1); } } return (0);}#endifintpcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf){#ifdef HAVE_SOLARIS int fd; union { u_int nunits; char pad[516]; /* XXX - must be at least 513; is 516 in "atmgetunits" */ } buf; char baname[2+1+1]; u_int i; /* * We may have to do special magic to get ATM devices. */ if ((fd = open("/dev/ba", O_RDWR)) < 0) { /* * We couldn't open the "ba" device. * For now, just give up; perhaps we should * return an error if the problem is neither * a "that device doesn't exist" error (ENOENT, * ENXIO, etc.) or a "you're not allowed to do * that" error (EPERM, EACCES). */ return (0); } if (strioctl(fd, A_GET_UNITS, sizeof(buf), (char *)&buf) < 0) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "A_GET_UNITS: %s", pcap_strerror(errno)); 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) return (-1); }#endif return (0);}static intsend_request(int fd, char *ptr, int len, char *what, char *ebuf){ struct strbuf ctl; int flags; ctl.maxlen = 0; ctl.len = len; ctl.buf = ptr; 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)); return (-1); } return (0);}static intrecv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror){ union DL_primitives *dlp; struct strbuf ctl; int flags; /* * Clear out "*uerror", so it's only set for DL_ERROR_ACK/DL_SYSERR, * making that the only place where EBUSY is treated specially. */ if (uerror != NULL) *uerror = 0; ctl.maxlen = MAXDLBUF; ctl.len = 0; ctl.buf = bufp; 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)); return (-1); } dlp = (union DL_primitives *) ctl.buf; switch (dlp->dl_primitive) { case DL_INFO_ACK: case DL_BIND_ACK: case DL_OK_ACK:#ifdef DL_HP_PPA_ACK case DL_HP_PPA_ACK:#endif /* These are OK */ break; case DL_ERROR_ACK: switch (dlp->error_ack.dl_errno) { 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)); break; default: snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: %s", what, dlstrerror(dlp->error_ack.dl_errno)); break; } return (-1); default: snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: Unexpected primitive ack %s", what, dlprim(dlp->dl_primitive)); return (-1); } if (ctl.len < size) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: Ack too small (%d < %d)", what, ctl.len, size); return (-1); } return (ctl.len);}static char *dlstrerror(bpf_u_int32 dl_errno){ static char errstring[6+2+8+1]; switch (dl_errno) { case DL_ACCESS: return ("Improper permissions for request"); case DL_BADADDR: return ("DLSAP addr in improper format or invalid"); case DL_BADCORR: return ("Seq number not from outstand DL_CONN_IND"); case DL_BADDATA: return ("User data exceeded provider limit"); case DL_BADPPA:#ifdef HAVE_DEV_DLPI /* * With a single "/dev/dlpi" device used for all * DLPI providers, PPAs have nothing to do with * unit numbers. */ return ("Specified PPA was invalid");#else /* * We have separate devices for separate devices; * the PPA is just the unit number. */ return ("Specified PPA (device unit) was invalid");#endif case DL_BADPRIM: return ("Primitive received not known by provider"); case DL_BADQOSPARAM: return ("QOS parameters contained invalid values"); case DL_BADQOSTYPE: return ("QOS structure type is unknown/unsupported"); case DL_BADSAP: return ("Bad LSAP selector"); case DL_BADTOKEN: return ("Token used not an active stream"); case DL_BOUND: return ("Attempted second bind with dl_max_conind"); case DL_INITFAILED: return ("Physical link initialization failed"); case DL_NOADDR: return ("Provider couldn't allocate alternate address"); case DL_NOTINIT: return ("Physical link not initialized"); case DL_OUTSTATE: return ("Primitive issued in improper state"); case DL_SYSERR: return ("UNIX system error occurred"); case DL_UNSUPPORTED: return ("Requested service not supplied by provider"); case DL_UNDELIVERABLE: return ("Previous data unit could not be delivered"); case DL_NOTSUPPORTED: return ("Primitive is known but not supported"); case DL_TOOMANY: return ("Limit exceeded"); case DL_NOTENAB: return ("Promiscuous mode not enabled"); case DL_BUSY: return ("Other streams for PPA in post-attached"); case DL_NOAUTO: return ("Automatic handling XID&TEST not supported"); case DL_NOXIDAUTO: return ("Automatic handling of XID not supported"); case DL_NOTESTAUTO: return ("Automatic handling of TEST not supported"); case DL_XIDAUTO: return ("Automatic handling of XID response"); case DL_TESTAUTO: return ("Automatic handling of TEST response"); case DL_PENDING: return ("Pending outstanding connect indications"); default: sprintf(errstring, "Error %02x", dl_errno); return (errstring); }}static char *dlprim(bpf_u_int32 prim){ static char primbuf[80]; switch (prim) { case DL_INFO_REQ: return ("DL_INFO_REQ"); case DL_INFO_ACK: return ("DL_INFO_ACK"); case DL_ATTACH_REQ: return ("DL_ATTACH_REQ"); case DL_DETACH_REQ: return ("DL_DETACH_REQ"); case DL_BIND_REQ: return ("DL_BIND_REQ"); case DL_BIND_ACK: return ("DL_BIND_ACK"); case DL_UNBIND_REQ: return ("DL_UNBIND_REQ"); case DL_OK_ACK: return ("DL_OK_ACK"); case DL_ERROR_ACK: return ("DL_ERROR_ACK"); case DL_SUBS_BIND_REQ: return ("DL_SUBS_BIND_REQ"); case DL_SUBS_BIND_ACK: return ("DL_SUBS_BIND_ACK"); case DL_UNITDATA_REQ: return ("DL_UNITDATA_REQ"); case DL_UNITDATA_IND: return ("DL_UNITDATA_IND"); case DL_UDERROR_IND: return ("DL_UDERROR_IND"); case DL_UDQOS_REQ: return ("DL_UDQOS_REQ"); case DL_CONNECT_REQ: return ("DL_CONNECT_REQ"); case DL_CONNECT_IND: return ("DL_CONNECT_IND"); case DL_CONNECT_RES: return ("DL_CONNECT_RES"); case DL_CONNECT_CON: return ("DL_CONNECT_CON"); case DL_TOKEN_REQ: return ("DL_TOKEN_REQ"); case DL_TOKEN_ACK: return ("DL_TOKEN_ACK"); case DL_DISCONNECT_REQ: return ("DL_DISCONNECT_REQ"); case DL_DISCONNECT_IND: return ("DL_DISCONNECT_IND"); case DL_RESET_REQ: return ("DL_RESET_REQ"); case DL_RESET_IND: return ("DL_RESET_IND"); case DL_RESET_RES: return ("DL_RESET_RES"); case DL_RESET_CON: return ("DL_RESET_CON");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -