#ifdef USE_LIBPCAP #include #include #include #include #include "pktlib.h" #include "lib.h" #define BUFFER_SIZE 65536 struct _pktif { struct _pktif_base base; /* 共通領域は先頭に置く必要がある */ struct { /* インターフェースのlibpcap依存部分 */ pcap_t *pcap_handle; char errbuf[PCAP_ERRBUF_SIZE]; #ifdef USE_WINPCAP char *ifname; #endif } libpcap; }; #ifdef USE_WINPCAP static char *interface_search(pktif_t pktif, char *ifname) { pcap_if_t *alldevs; pcap_if_t *d; int i, n = -1; if (ifname[0] != '-') n = atoi(ifname); if (pcap_findalldevs(&alldevs, pktif->libpcap.errbuf) < 0) pktlib_error_exit("Cannot find devices.\n"); if (n < 0) { fprintf(stderr, "Available interface list:\n"); } pktif->libpcap.ifname = NULL; i = 0; for (d = alldevs; d; d = d->next) { if (n < 0) { fprintf(stderr, "\t%d\t%s\n", i, d->description ? d->description : "No description"); } else { if (i == n) { pktif->libpcap.ifname = strdup(d->name); break; } } i++; } pcap_freealldevs(alldevs); return pktif->libpcap.ifname; } #endif pktif_t pktif_open(char *ifname, unsigned long flags, int option_size) { pktif_t pktif; int size, fd, linktype, buffer_size = BUFFER_SIZE; pcap_t *pcap_handle; size = sizeof(*pktif) + option_size + strlen(ifname) + 1; pktif = malloc(size); memset(pktif, 0, size); #ifdef USE_WINPCAP ifname = interface_search(pktif, ifname); if (ifname == NULL) pktlib_error_exit("Unknown interface.\n"); #endif pcap_handle = pcap_open_live(ifname, buffer_size, !(flags & PKTIF_OPEN_FLAG_RECV_NOTPROM) ? 1 : 0, 50, pktif->libpcap.errbuf); if (pcap_handle == NULL) pktlib_error_exit("Cannot open libpcap.\n"); /* 情報の取得 */ #ifndef USE_WINPCAP fd = pcap_get_selectable_fd(pcap_handle); #else fd = -1; flags |= PKTIF_OPEN_FLAG_SELECT_DISABLE; #endif if (fd < 0) flags |= PKTIF_OPEN_FLAG_SELECT_NOSELECT; /* 受信関連の設定 */ #ifndef USE_WINPCAP if (flags & PKTIF_OPEN_FLAG_RECV_NOTSENT) { if (pcap_setdirection(pcap_handle, PCAP_D_IN) < 0) pktlib_error_exit("Fail to libpcap setdirection.\n"); } #endif /* リンクタイプの取得 */ linktype = pcap_datalink(pcap_handle); pktif->base.next = NULL; pktif->base.name = (char *)(pktif + 1) + option_size; strcpy(pktif->base.name, ifname); pktif->base.fd = fd; pktif->base.flags = flags; pktif->base.linktype = linktype; pktif->base.buffer_size = buffer_size; pktif->base.option = (option_size> 0) ? (pktif + 1) : NULL; pktif->libpcap.pcap_handle = pcap_handle; pktlib_iflist_set(pktif); /* select()のためにリンクリストに接続する */ return pktif; } int pktif_is_empty(pktif_t pktif) { return 1; /* BPFとの整合性のための関数.常に1を返す */ } struct recv_userdata { struct pcap_pkthdr *header; const unsigned char **buffer; }; static void recv_proc(unsigned char *user, const struct pcap_pkthdr *header, const unsigned char *buffer) { struct recv_userdata *rud = (struct recv_userdata *)user; memcpy(rud->header, header, sizeof(*(rud->header))); *(rud->buffer) = buffer; } int pktif_recv(pktif_t pktif, char *buffer, int size, struct timeval *tm) { int r; const unsigned char *pktbuf; struct pcap_pkthdr header; struct recv_userdata rud; rud.header = &header; rud.buffer = &pktbuf; r = pcap_loop(pktif->libpcap.pcap_handle, 1, recv_proc, (unsigned char *)&rud); if (r < 0) pktlib_error_exit("Interface down.\n"); if (tm) { tm->tv_sec = header.ts.tv_sec; tm->tv_usec = header.ts.tv_usec; } r = header.caplen; if (r>= size) pktlib_error_exit("Out of buffer.\n"); memcpy(buffer, pktbuf, r); return r; } int pktif_send(pktif_t pktif, char *buffer, int size) { int r; r = pcap_sendpacket(pktif->libpcap.pcap_handle, (unsigned char *)buffer, size); return (r < 0) ? -1 : size; } #endif

AltStyle によって変換されたページ (->オリジナル) /