📄 pcap-win32.c
字号:
}pcap_t *pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf){ register pcap_t *p; NetType type;#ifdef HAVE_REMOTE char host[PCAP_BUF_SIZE + 1]; char port[PCAP_BUF_SIZE + 1]; char name[PCAP_BUF_SIZE + 1]; int srctype; /* Retrofit; we have to make older applications compatible with the remote capture So, we're calling the pcap_open_remote() from here, that is a very dirty thing. Obviously, we cannot exploit all the new features; for instance, we cannot send authentication, we cannot use a UDP data connection, and so on. */ if (pcap_parsesrcstr(device, &srctype, host, port, name, ebuf) ) return NULL; if (srctype == PCAP_SRC_IFREMOTE) { p= pcap_opensource_remote(device, NULL, ebuf); if (p == NULL) return NULL; p->snapshot= snaplen; p->timeout= to_ms; p->rmt_flags= (promisc) ? PCAP_OPENFLAG_PROMISCUOUS : 0; return p; }#endif /* HAVE_REMOTE */ /* Init WinSock */ wsockinit(); p = (pcap_t *)malloc(sizeof(*p)); if (p == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return (NULL); } memset(p, 0, sizeof(*p)); p->adapter=NULL; p->adapter = PacketOpenAdapter((char*)device); if (p->adapter == NULL) { free(p); /* Adapter detected but we are not able to open it. Return failure. */ snprintf(ebuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror()); return NULL; } /*get network type*/ if(PacketGetNetType (p->adapter,&type) == FALSE) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror()); goto bad; } /*Set the linktype*/ switch (type.LinkType) { case NdisMediumWan: p->linktype = DLT_EN10MB; break; case NdisMedium802_3: p->linktype = DLT_EN10MB; /* * This is (presumably) a real Ethernet capture; give it a * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so * that an application can let you choose it, in case you're * capturing DOCSIS traffic that a Cisco Cable Modem * Termination System is putting out onto an Ethernet (it * doesn't put an Ethernet header onto the wire, it puts raw * DOCSIS frames out on the wire inside the low-level * Ethernet framing). */ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); /* * If that fails, just leave the list empty. */ if (p->dlt_list != NULL) { p->dlt_list[0] = DLT_EN10MB; p->dlt_list[1] = DLT_DOCSIS; p->dlt_count = 2; } break; case NdisMediumFddi: p->linktype = DLT_FDDI; break; case NdisMedium802_5: p->linktype = DLT_IEEE802; break; case NdisMediumArcnetRaw: p->linktype = DLT_ARCNET; break; case NdisMediumArcnet878_2: p->linktype = DLT_ARCNET; break; case NdisMediumAtm: p->linktype = DLT_ATM_RFC1483; break; case NdisMediumCHDLC: p->linktype = DLT_CHDLC; break; case NdisMediumPPPSerial: p->linktype = DLT_PPP_SERIAL; break; case NdisMediumNull: p->linktype = DLT_NULL; break; case NdisMediumBare80211: p->linktype = DLT_IEEE802_11; break; case NdisMediumRadio80211: p->linktype = DLT_IEEE802_11_RADIO; break; default: p->linktype = DLT_EN10MB; /*an unknown adapter is assumed to be ethernet*/ break; } /* Set promisquous mode */ if (promisc) PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS); else PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL); /* Set the buffer size */ p->bufsize = PcapBufSize; /* Store the timeout. Used by pcap_setnonblock() */ p->timeout= to_ms; /* allocate Packet structure used during the capture */ if((p->Packet = PacketAllocatePacket())==NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure"); goto bad; } if(!(p->adapter->Flags & INFO_FLAG_DAG_CARD)) { /* * Traditional Adapter */ p->buffer = (u_char *)malloc(PcapBufSize); if (p->buffer == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); goto bad; } PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize); p->snapshot = snaplen; /* allocate the standard buffer in the driver */ if(PacketSetBuff( p->adapter, SIZE_BUF)==FALSE) { snprintf(ebuf, PCAP_ERRBUF_SIZE,"driver error: not enough memory to allocate the kernel buffer\n"); goto bad; } /* tell the driver to copy the buffer only if it contains at least 16K */ if(PacketSetMinToCopy(p->adapter,16000)==FALSE) { snprintf(ebuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s\n", pcap_win32strerror()); goto bad; } } else#ifdef HAVE_DAG_API { /* * Dag Card */ LONG status; HKEY dagkey; DWORD lptype; DWORD lpcbdata; int postype = 0; char keyname[512]; snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s", "SYSTEM\\CurrentControlSet\\Services\\DAG", strstr(_strlwr((char*)device), "dag")); do { status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &dagkey); if(status != ERROR_SUCCESS) break; status = RegQueryValueEx(dagkey, "PosType", NULL, &lptype, (char*)&postype, &lpcbdata); if(status != ERROR_SUCCESS) { postype = 0; } RegCloseKey(dagkey); } while(FALSE); p->snapshot = PacketSetSnapLen(p->adapter, snaplen); /* Set the length of the FCS associated to any packet. This value * will be subtracted to the packet length */ p->md.dag_fcs_bits = p->adapter->DagFcsLen; }#else goto bad;#endif /* HAVE_DAG_API */ PacketSetReadTimeout(p->adapter, to_ms); #ifdef HAVE_DAG_API if(p->adapter->Flags & INFO_FLAG_DAG_CARD) { /* install dag specific handlers for read and setfilter */ p->read_op = pcap_read_win32_dag; p->setfilter_op = pcap_setfilter_win32_dag; } else {#endif /* HAVE_DAG_API */ /* install traditional npf handlers for read and setfilter */ p->read_op = pcap_read_win32_npf; p->setfilter_op = pcap_setfilter_win32_npf;#ifdef HAVE_DAG_API }#endif /* HAVE_DAG_API */ p->setdirection_op = NULL; /* Not implemented. */ /* XXX - can this be implemented on some versions of Windows? */ p->inject_op = pcap_inject_win32; p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_win32; p->setnonblock_op = pcap_setnonblock_win32; p->stats_op = pcap_stats_win32; p->close_op = pcap_close_win32; return (p);bad: if (p->adapter) PacketCloseAdapter(p->adapter); if (p->buffer != NULL) free(p->buffer); if(p->Packet) PacketFreePacket(p->Packet); /* * Get rid of any link-layer type list we allocated. */ if (p->dlt_list != NULL) free(p->dlt_list); free(p); return (NULL);}static intpcap_setfilter_win32_npf(pcap_t *p, struct bpf_program *fp){ if(PacketSetBpf(p->adapter,fp)==FALSE){ /* * Kernel filter not installed. * XXX - fall back on userland filtering, as is done * on other platforms? */ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Driver error: cannot set bpf filter: %s", pcap_win32strerror()); return (-1); } /* * Discard any previously-received packets, as they might have * passed whatever filter was formerly in effect, but might * not pass this filter (BIOCSETF discards packets buffered * in the kernel, so you can lose packets in any case). */ p->cc = 0; return (0);}/* * We filter at user level, since the kernel driver does't process the packets */static int pcap_setfilter_win32_dag(pcap_t *p, struct bpf_program *fp) { if(!fp) { strncpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf)); return -1; } /* Install a user level filter */ if (install_bpf_program(p, fp) < 0) { snprintf(p->errbuf, sizeof(p->errbuf), "setfilter, unable to install the filter: %s", pcap_strerror(errno)); return -1; } p->md.use_bpf = 0; return (0);}static intpcap_getnonblock_win32(pcap_t *p, char *errbuf){ /* * XXX - if there were a PacketGetReadTimeout() call, we * would use it, and return 1 if the timeout is -1 * and 0 otherwise. */ return (p->nonblock);}static intpcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf){ int newtimeout; if (nonblock) { /* * Set the read timeout to -1 for non-blocking mode. */ newtimeout = -1; } else { /* * Restore the timeout set when the device was opened. * (Note that this may be -1, in which case we're not * really leaving non-blocking mode.) */ newtimeout = p->timeout; } if (!PacketSetReadTimeout(p->adapter, newtimeout)) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketSetReadTimeout: %s", pcap_win32strerror()); return (-1); } p->nonblock = (newtimeout == -1); return (0);}/* Set the driver working mode */int pcap_setmode(pcap_t *p, int mode){ if (p->adapter==NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "impossible to set mode while reading from a file"); return -1; } if(PacketSetMode(p->adapter,mode)==FALSE) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized"); return -1; } return 0;}/* Set the dimension of the kernel-level capture buffer */int pcap_setbuff(pcap_t *p, int dim){#ifdef HAVE_REMOTE if (p->rmt_clientside) { /* Currently, this is a bug: the capture buffer cannot be set with remote capture */ return 0; }#endif /* HAVE_REMOTE */ if (p->adapter==NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "The kernel buffer size cannot be set while reading from a file"); return -1; } if(PacketSetBuff(p->adapter,dim)==FALSE) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer"); return -1; } return 0;}/*set the minimum amount of data that will release a read call*/int pcap_setmintocopy(pcap_t *p, int size){ if (p->adapter==NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Impossible to set the mintocopy parameter on an offline capture"); return -1; } if(PacketSetMinToCopy(p->adapter, size)==FALSE) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size"); return -1; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -