1127664Sbms/* 2172677Smlaier * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy) 3190225Srpaulo * Copyright (c) 2005 - 2008 CACE Technologies, Davis (California) 4127664Sbms * All rights reserved. 5127664Sbms * 6127664Sbms * Redistribution and use in source and binary forms, with or without 7127664Sbms * modification, are permitted provided that the following conditions 8127664Sbms * are met: 9127664Sbms * 10127664Sbms * 1. Redistributions of source code must retain the above copyright 11127664Sbms * notice, this list of conditions and the following disclaimer. 12127664Sbms * 2. Redistributions in binary form must reproduce the above copyright 13127664Sbms * notice, this list of conditions and the following disclaimer in the 14127664Sbms * documentation and/or other materials provided with the distribution. 15172677Smlaier * 3. Neither the name of the Politecnico di Torino, CACE Technologies 16172677Smlaier * nor the names of its contributors may be used to endorse or promote 17172677Smlaier * products derived from this software without specific prior written 18172677Smlaier * permission. 19127664Sbms * 20127664Sbms * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21127664Sbms * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22127664Sbms * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23127664Sbms * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24127664Sbms * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25127664Sbms * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26127664Sbms * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27127664Sbms * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28127664Sbms * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29127664Sbms * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30127664Sbms * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31127664Sbms * 32127664Sbms */ 33127664Sbms 34127664Sbms#ifndef lint 35127664Sbmsstatic const char rcsid[] _U_ = 36214518Srpaulo "@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.42 2008-05-21 22:15:25 gianluca Exp $ (LBL)"; 37127664Sbms#endif 38127664Sbms 39127664Sbms#include <pcap-int.h> 40172677Smlaier#include <Packet32.h> 41190225Srpaulo#ifdef __MINGW32__ 42235426Sdelphij#ifdef __MINGW64__ 43235426Sdelphij#include <ntddndis.h> 44235426Sdelphij#else /*__MINGW64__*/ 45235426Sdelphij#include <ddk/ntddndis.h> 46190225Srpaulo#include <ddk/ndis.h> 47235426Sdelphij#endif /*__MINGW64__*/ 48190225Srpaulo#else /*__MINGW32__*/ 49190225Srpaulo#include <ntddndis.h> 50190225Srpaulo#endif /*__MINGW32__*/ 51146768Ssam#ifdef HAVE_DAG_API 52146768Ssam#include <dagnew.h> 53146768Ssam#include <dagapi.h> 54146768Ssam#endif /* HAVE_DAG_API */ 55127664Sbms#ifdef __MINGW32__ 56127664Sbmsint* _errno(); 57127664Sbms#define errno (*_errno()) 58127664Sbms#endif /* __MINGW32__ */ 59127664Sbms 60146768Ssamstatic int pcap_setfilter_win32_npf(pcap_t *, struct bpf_program *); 61146768Ssamstatic int pcap_setfilter_win32_dag(pcap_t *, struct bpf_program *); 62127664Sbmsstatic int pcap_getnonblock_win32(pcap_t *, char *); 63127664Sbmsstatic int pcap_setnonblock_win32(pcap_t *, int, char *); 64127664Sbms 65190225Srpaulo/*dimension of the buffer in the pcap_t structure*/ 66190225Srpaulo#define WIN32_DEFAULT_USER_BUFFER_SIZE 256000 67127664Sbms 68190225Srpaulo/*dimension of the buffer in the kernel driver NPF */ 69190225Srpaulo#define WIN32_DEFAULT_KERNEL_BUFFER_SIZE 1000000 70190225Srpaulo 71146768Ssam/* Equivalent to ntohs(), but a lot faster under Windows */ 72146768Ssam#define SWAPS(_X) ((_X & 0xff) << 8) | (_X >> 8) 73146768Ssam 74127664Sbms/* 75127664Sbms * Header that the WinPcap driver associates to the packets. 76127664Sbms * Once was in bpf.h 77127664Sbms */ 78127664Sbmsstruct bpf_hdr { 79127664Sbms struct timeval bh_tstamp; /* time stamp */ 80127664Sbms bpf_u_int32 bh_caplen; /* length of captured portion */ 81127664Sbms bpf_u_int32 bh_datalen; /* original length of packet */ 82127664Sbms u_short bh_hdrlen; /* length of bpf header (this struct 83127664Sbms plus alignment padding) */ 84127664Sbms}; 85127664Sbms 86214518SrpauloCRITICAL_SECTION g_PcapCompileCriticalSection; 87214518Srpaulo 88214518SrpauloBOOL WINAPI DllMain( 89214518Srpaulo HANDLE hinstDLL, 90214518Srpaulo DWORD dwReason, 91214518Srpaulo LPVOID lpvReserved 92214518Srpaulo) 93214518Srpaulo{ 94214518Srpaulo if (dwReason == DLL_PROCESS_ATTACH) 95214518Srpaulo { 96214518Srpaulo InitializeCriticalSection(&g_PcapCompileCriticalSection); 97214518Srpaulo } 98214518Srpaulo 99214518Srpaulo return TRUE; 100214518Srpaulo} 101214518Srpaulo 102127664Sbms/* Start winsock */ 103127664Sbmsint 104127664Sbmswsockinit() 105127664Sbms{ 106127664Sbms WORD wVersionRequested; 107127664Sbms WSADATA wsaData; 108127664Sbms int err; 109127664Sbms wVersionRequested = MAKEWORD( 1, 1); 110127664Sbms err = WSAStartup( wVersionRequested, &wsaData ); 111127664Sbms if ( err != 0 ) 112127664Sbms { 113127664Sbms return -1; 114127664Sbms } 115127664Sbms return 0; 116127664Sbms} 117127664Sbms 118127664Sbms 119127664Sbmsstatic int 120127664Sbmspcap_stats_win32(pcap_t *p, struct pcap_stat *ps) 121127664Sbms{ 122127664Sbms 123127664Sbms if(PacketGetStats(p->adapter, (struct bpf_stat*)ps) != TRUE){ 124127664Sbms snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketGetStats error: %s", pcap_win32strerror()); 125127664Sbms return -1; 126127664Sbms } 127127664Sbms 128127664Sbms return 0; 129127664Sbms} 130127664Sbms 131190225Srpaulo/* Set the dimension of the kernel-level capture buffer */ 132127664Sbmsstatic int 133190225Srpaulopcap_setbuff_win32(pcap_t *p, int dim) 134190225Srpaulo{ 135190225Srpaulo if(PacketSetBuff(p->adapter,dim)==FALSE) 136190225Srpaulo { 137190225Srpaulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer"); 138190225Srpaulo return -1; 139190225Srpaulo } 140190225Srpaulo return 0; 141190225Srpaulo} 142190225Srpaulo 143190225Srpaulo/* Set the driver working mode */ 144190225Srpaulostatic int 145190225Srpaulopcap_setmode_win32(pcap_t *p, int mode) 146190225Srpaulo{ 147190225Srpaulo if(PacketSetMode(p->adapter,mode)==FALSE) 148190225Srpaulo { 149190225Srpaulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized"); 150190225Srpaulo return -1; 151190225Srpaulo } 152190225Srpaulo 153190225Srpaulo return 0; 154190225Srpaulo} 155190225Srpaulo 156190225Srpaulo/*set the minimum amount of data that will release a read call*/ 157190225Srpaulostatic int 158190225Srpaulopcap_setmintocopy_win32(pcap_t *p, int size) 159190225Srpaulo{ 160190225Srpaulo if(PacketSetMinToCopy(p->adapter, size)==FALSE) 161190225Srpaulo { 162190225Srpaulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size"); 163190225Srpaulo return -1; 164190225Srpaulo } 165190225Srpaulo return 0; 166190225Srpaulo} 167190225Srpaulo 168190225Srpaulostatic int 169146768Ssampcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 170127664Sbms{ 171127664Sbms int cc; 172127664Sbms int n = 0; 173127664Sbms register u_char *bp, *ep; 174127664Sbms 175127664Sbms cc = p->cc; 176127664Sbms if (p->cc == 0) { 177127664Sbms /* 178127664Sbms * Has "pcap_breakloop()" been called? 179127664Sbms */ 180127664Sbms if (p->break_loop) { 181127664Sbms /* 182127664Sbms * Yes - clear the flag that indicates that it 183127664Sbms * has, and return -2 to indicate that we were 184127664Sbms * told to break out of the loop. 185127664Sbms */ 186127664Sbms p->break_loop = 0; 187127664Sbms return (-2); 188127664Sbms } 189127664Sbms 190127664Sbms /* capture the packets */ 191127664Sbms if(PacketReceivePacket(p->adapter,p->Packet,TRUE)==FALSE){ 192127664Sbms snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed"); 193127664Sbms return (-1); 194127664Sbms } 195127664Sbms 196127664Sbms cc = p->Packet->ulBytesReceived; 197127664Sbms 198127664Sbms bp = p->Packet->Buffer; 199127664Sbms } 200127664Sbms else 201127664Sbms bp = p->bp; 202127664Sbms 203127664Sbms /* 204127664Sbms * Loop through each packet. 205127664Sbms */ 206127664Sbms#define bhp ((struct bpf_hdr *)bp) 207127664Sbms ep = bp + cc; 208127664Sbms while (1) { 209127664Sbms register int caplen, hdrlen; 210127664Sbms 211127664Sbms /* 212127664Sbms * Has "pcap_breakloop()" been called? 213127664Sbms * If so, return immediately - if we haven't read any 214127664Sbms * packets, clear the flag and return -2 to indicate 215127664Sbms * that we were told to break out of the loop, otherwise 216127664Sbms * leave the flag set, so that the *next* call will break 217127664Sbms * out of the loop without having read any packets, and 218127664Sbms * return the number of packets we've processed so far. 219127664Sbms */ 220127664Sbms if (p->break_loop) { 221127664Sbms if (n == 0) { 222127664Sbms p->break_loop = 0; 223127664Sbms return (-2); 224127664Sbms } else { 225127664Sbms p->bp = bp; 226127664Sbms p->cc = ep - bp; 227127664Sbms return (n); 228127664Sbms } 229127664Sbms } 230127664Sbms if (bp >= ep) 231127664Sbms break; 232127664Sbms 233127664Sbms caplen = bhp->bh_caplen; 234127664Sbms hdrlen = bhp->bh_hdrlen; 235127664Sbms 236127664Sbms /* 237127664Sbms * XXX A bpf_hdr matches a pcap_pkthdr. 238127664Sbms */ 239127664Sbms (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen); 240235426Sdelphij bp += Packet_WORDALIGN(caplen + hdrlen); 241127664Sbms if (++n >= cnt && cnt > 0) { 242127664Sbms p->bp = bp; 243127664Sbms p->cc = ep - bp; 244127664Sbms return (n); 245127664Sbms } 246127664Sbms } 247127664Sbms#undef bhp 248127664Sbms p->cc = 0; 249127664Sbms return (n); 250127664Sbms} 251127664Sbms 252146768Ssam#ifdef HAVE_DAG_API 253146768Ssamstatic int 254146768Ssampcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 255146768Ssam{ 256146768Ssam u_char *dp = NULL; 257146768Ssam int packet_len = 0, caplen = 0; 258146768Ssam struct pcap_pkthdr pcap_header; 259146768Ssam u_char *endofbuf; 260146768Ssam int n = 0; 261146768Ssam dag_record_t *header; 262146768Ssam unsigned erf_record_len; 263146768Ssam ULONGLONG ts; 264146768Ssam int cc; 265146768Ssam unsigned swt; 266146768Ssam unsigned dfp = p->adapter->DagFastProcess; 267127664Sbms 268146768Ssam cc = p->cc; 269146768Ssam if (cc == 0) /* Get new packets only if we have processed all the ones of the previous read */ 270146768Ssam { 271146768Ssam /* Get new packets from the network */ 272146768Ssam if(PacketReceivePacket(p->adapter, p->Packet, TRUE)==FALSE){ 273146768Ssam snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed"); 274146768Ssam return (-1); 275146768Ssam } 276146768Ssam 277146768Ssam cc = p->Packet->ulBytesReceived; 278146768Ssam if(cc == 0) 279146768Ssam /* The timeout has expired but we no packets arrived */ 280146768Ssam return 0; 281146768Ssam header = (dag_record_t*)p->adapter->DagBuffer; 282146768Ssam } 283146768Ssam else 284146768Ssam header = (dag_record_t*)p->bp; 285146768Ssam 286146768Ssam endofbuf = (char*)header + cc; 287146768Ssam 288146768Ssam /* 289146768Ssam * Cycle through the packets 290146768Ssam */ 291146768Ssam do 292146768Ssam { 293146768Ssam erf_record_len = SWAPS(header->rlen); 294146768Ssam if((char*)header + erf_record_len > endofbuf) 295146768Ssam break; 296146768Ssam 297146768Ssam /* Increase the number of captured packets */ 298146768Ssam p->md.stat.ps_recv++; 299146768Ssam 300146768Ssam /* Find the beginning of the packet */ 301146768Ssam dp = ((u_char *)header) + dag_record_size; 302146768Ssam 303146768Ssam /* Determine actual packet len */ 304146768Ssam switch(header->type) 305146768Ssam { 306146768Ssam case TYPE_ATM: 307146768Ssam packet_len = ATM_SNAPLEN; 308146768Ssam caplen = ATM_SNAPLEN; 309146768Ssam dp += 4; 310146768Ssam 311146768Ssam break; 312146768Ssam 313146768Ssam case TYPE_ETH: 314146768Ssam swt = SWAPS(header->wlen); 315146768Ssam packet_len = swt - (p->md.dag_fcs_bits); 316146768Ssam caplen = erf_record_len - dag_record_size - 2; 317146768Ssam if (caplen > packet_len) 318146768Ssam { 319146768Ssam caplen = packet_len; 320146768Ssam } 321146768Ssam dp += 2; 322146768Ssam 323146768Ssam break; 324146768Ssam 325146768Ssam case TYPE_HDLC_POS: 326146768Ssam swt = SWAPS(header->wlen); 327146768Ssam packet_len = swt - (p->md.dag_fcs_bits); 328146768Ssam caplen = erf_record_len - dag_record_size; 329146768Ssam if (caplen > packet_len) 330146768Ssam { 331146768Ssam caplen = packet_len; 332146768Ssam } 333146768Ssam 334146768Ssam break; 335146768Ssam } 336146768Ssam 337146768Ssam if(caplen > p->snapshot) 338146768Ssam caplen = p->snapshot; 339146768Ssam 340146768Ssam /* 341146768Ssam * Has "pcap_breakloop()" been called? 342146768Ssam * If so, return immediately - if we haven't read any 343146768Ssam * packets, clear the flag and return -2 to indicate 344146768Ssam * that we were told to break out of the loop, otherwise 345146768Ssam * leave the flag set, so that the *next* call will break 346146768Ssam * out of the loop without having read any packets, and 347146768Ssam * return the number of packets we've processed so far. 348146768Ssam */ 349146768Ssam if (p->break_loop) 350146768Ssam { 351146768Ssam if (n == 0) 352146768Ssam { 353146768Ssam p->break_loop = 0; 354146768Ssam return (-2); 355146768Ssam } 356146768Ssam else 357146768Ssam { 358146768Ssam p->bp = (char*)header; 359146768Ssam p->cc = endofbuf - (char*)header; 360146768Ssam return (n); 361146768Ssam } 362146768Ssam } 363146768Ssam 364146768Ssam if(!dfp) 365146768Ssam { 366146768Ssam /* convert between timestamp formats */ 367146768Ssam ts = header->ts; 368146768Ssam pcap_header.ts.tv_sec = (int)(ts >> 32); 369146768Ssam ts = (ts & 0xffffffffi64) * 1000000; 370146768Ssam ts += 0x80000000; /* rounding */ 371146768Ssam pcap_header.ts.tv_usec = (int)(ts >> 32); 372146768Ssam if (pcap_header.ts.tv_usec >= 1000000) { 373146768Ssam pcap_header.ts.tv_usec -= 1000000; 374146768Ssam pcap_header.ts.tv_sec++; 375146768Ssam } 376146768Ssam } 377146768Ssam 378146768Ssam /* No underlaying filtering system. We need to filter on our own */ 379146768Ssam if (p->fcode.bf_insns) 380146768Ssam { 381146768Ssam if (bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen) == 0) 382146768Ssam { 383146768Ssam /* Move to next packet */ 384146768Ssam header = (dag_record_t*)((char*)header + erf_record_len); 385146768Ssam continue; 386146768Ssam } 387146768Ssam } 388146768Ssam 389146768Ssam /* Fill the header for the user suppplied callback function */ 390146768Ssam pcap_header.caplen = caplen; 391146768Ssam pcap_header.len = packet_len; 392146768Ssam 393146768Ssam /* Call the callback function */ 394146768Ssam (*callback)(user, &pcap_header, dp); 395146768Ssam 396146768Ssam /* Move to next packet */ 397146768Ssam header = (dag_record_t*)((char*)header + erf_record_len); 398146768Ssam 399146768Ssam /* Stop if the number of packets requested by user has been reached*/ 400146768Ssam if (++n >= cnt && cnt > 0) 401146768Ssam { 402146768Ssam p->bp = (char*)header; 403146768Ssam p->cc = endofbuf - (char*)header; 404146768Ssam return (n); 405146768Ssam } 406146768Ssam } 407146768Ssam while((u_char*)header < endofbuf); 408146768Ssam 409146768Ssam return 1; 410146768Ssam} 411146768Ssam#endif /* HAVE_DAG_API */ 412146768Ssam 413146768Ssam/* Send a packet to the network */ 414146768Ssamstatic int 415146768Ssampcap_inject_win32(pcap_t *p, const void *buf, size_t size){ 416146768Ssam LPPACKET PacketToSend; 417146768Ssam 418146768Ssam PacketToSend=PacketAllocatePacket(); 419146768Ssam 420146768Ssam if (PacketToSend == NULL) 421146768Ssam { 422146768Ssam snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketAllocatePacket failed"); 423146768Ssam return -1; 424146768Ssam } 425146768Ssam 426146768Ssam PacketInitPacket(PacketToSend,(PVOID)buf,size); 427146768Ssam if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){ 428146768Ssam snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketSendPacket failed"); 429146768Ssam PacketFreePacket(PacketToSend); 430146768Ssam return -1; 431146768Ssam } 432146768Ssam 433146768Ssam PacketFreePacket(PacketToSend); 434146768Ssam 435146768Ssam /* 436146768Ssam * We assume it all got sent if "PacketSendPacket()" succeeded. 437146768Ssam * "pcap_inject()" is expected to return the number of bytes 438146768Ssam * sent. 439146768Ssam */ 440146768Ssam return size; 441146768Ssam} 442146768Ssam 443127664Sbmsstatic void 444190225Srpaulopcap_cleanup_win32(pcap_t *p) 445127664Sbms{ 446127664Sbms if (p->adapter != NULL) { 447127664Sbms PacketCloseAdapter(p->adapter); 448127664Sbms p->adapter = NULL; 449127664Sbms } 450146768Ssam if (p->Packet) { 451146768Ssam PacketFreePacket(p->Packet); 452146768Ssam p->Packet = NULL; 453146768Ssam } 454190225Srpaulo pcap_cleanup_live_common(p); 455127664Sbms} 456127664Sbms 457190225Srpaulostatic int 458190225Srpaulopcap_activate_win32(pcap_t *p) 459127664Sbms{ 460127664Sbms NetType type; 461127664Sbms 462190225Srpaulo if (p->opt.rfmon) { 463190225Srpaulo /* 464190225Srpaulo * No monitor mode on Windows. It could be done on 465190225Srpaulo * Vista with drivers that support the native 802.11 466190225Srpaulo * mechanism and monitor mode. 467190225Srpaulo */ 468190225Srpaulo return (PCAP_ERROR_RFMON_NOTSUP); 469190225Srpaulo } 470190225Srpaulo 471127664Sbms /* Init WinSock */ 472127664Sbms wsockinit(); 473127664Sbms 474190225Srpaulo p->adapter = PacketOpenAdapter(p->opt.source); 475127664Sbms 476127664Sbms if (p->adapter == NULL) 477127664Sbms { 478127664Sbms /* Adapter detected but we are not able to open it. Return failure. */ 479190225Srpaulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror()); 480190225Srpaulo return PCAP_ERROR; 481127664Sbms } 482127664Sbms 483127664Sbms /*get network type*/ 484127664Sbms if(PacketGetNetType (p->adapter,&type) == FALSE) 485127664Sbms { 486190225Srpaulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror()); 487127664Sbms goto bad; 488127664Sbms } 489127664Sbms 490127664Sbms /*Set the linktype*/ 491127664Sbms switch (type.LinkType) 492127664Sbms { 493127664Sbms case NdisMediumWan: 494127664Sbms p->linktype = DLT_EN10MB; 495127664Sbms break; 496127664Sbms 497127664Sbms case NdisMedium802_3: 498127664Sbms p->linktype = DLT_EN10MB; 499146768Ssam /* 500146768Ssam * This is (presumably) a real Ethernet capture; give it a 501146768Ssam * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so 502146768Ssam * that an application can let you choose it, in case you're 503146768Ssam * capturing DOCSIS traffic that a Cisco Cable Modem 504146768Ssam * Termination System is putting out onto an Ethernet (it 505146768Ssam * doesn't put an Ethernet header onto the wire, it puts raw 506146768Ssam * DOCSIS frames out on the wire inside the low-level 507146768Ssam * Ethernet framing). 508146768Ssam */ 509146768Ssam p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); 510146768Ssam /* 511146768Ssam * If that fails, just leave the list empty. 512146768Ssam */ 513146768Ssam if (p->dlt_list != NULL) { 514146768Ssam p->dlt_list[0] = DLT_EN10MB; 515146768Ssam p->dlt_list[1] = DLT_DOCSIS; 516146768Ssam p->dlt_count = 2; 517146768Ssam } 518127664Sbms break; 519127664Sbms 520127664Sbms case NdisMediumFddi: 521127664Sbms p->linktype = DLT_FDDI; 522127664Sbms break; 523127664Sbms 524127664Sbms case NdisMedium802_5: 525127664Sbms p->linktype = DLT_IEEE802; 526127664Sbms break; 527127664Sbms 528127664Sbms case NdisMediumArcnetRaw: 529127664Sbms p->linktype = DLT_ARCNET; 530127664Sbms break; 531127664Sbms 532127664Sbms case NdisMediumArcnet878_2: 533127664Sbms p->linktype = DLT_ARCNET; 534127664Sbms break; 535127664Sbms 536127664Sbms case NdisMediumAtm: 537127664Sbms p->linktype = DLT_ATM_RFC1483; 538127664Sbms break; 539127664Sbms 540146768Ssam case NdisMediumCHDLC: 541146768Ssam p->linktype = DLT_CHDLC; 542146768Ssam break; 543146768Ssam 544146768Ssam case NdisMediumPPPSerial: 545146768Ssam p->linktype = DLT_PPP_SERIAL; 546146768Ssam break; 547146768Ssam 548146768Ssam case NdisMediumNull: 549146768Ssam p->linktype = DLT_NULL; 550146768Ssam break; 551146768Ssam 552172677Smlaier case NdisMediumBare80211: 553172677Smlaier p->linktype = DLT_IEEE802_11; 554172677Smlaier break; 555172677Smlaier 556172677Smlaier case NdisMediumRadio80211: 557172677Smlaier p->linktype = DLT_IEEE802_11_RADIO; 558172677Smlaier break; 559172677Smlaier 560172677Smlaier case NdisMediumPpi: 561172677Smlaier p->linktype = DLT_PPI; 562172677Smlaier break; 563172677Smlaier 564127664Sbms default: 565127664Sbms p->linktype = DLT_EN10MB; /*an unknown adapter is assumed to be ethernet*/ 566127664Sbms break; 567127664Sbms } 568127664Sbms 569172677Smlaier /* Set promiscuous mode */ 570190225Srpaulo if (p->opt.promisc) 571172677Smlaier { 572127664Sbms 573172677Smlaier if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS) == FALSE) 574172677Smlaier { 575190225Srpaulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to promiscuous mode"); 576172677Smlaier goto bad; 577172677Smlaier } 578172677Smlaier } 579172677Smlaier else 580172677Smlaier { 581172677Smlaier if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL) == FALSE) 582172677Smlaier { 583190225Srpaulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to non-promiscuous mode"); 584172677Smlaier goto bad; 585172677Smlaier } 586172677Smlaier } 587172677Smlaier 588127664Sbms /* Set the buffer size */ 589190225Srpaulo p->bufsize = WIN32_DEFAULT_USER_BUFFER_SIZE; 590127664Sbms 591127664Sbms /* allocate Packet structure used during the capture */ 592127664Sbms if((p->Packet = PacketAllocatePacket())==NULL) 593127664Sbms { 594190225Srpaulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure"); 595127664Sbms goto bad; 596127664Sbms } 597127664Sbms 598146768Ssam if(!(p->adapter->Flags & INFO_FLAG_DAG_CARD)) 599127664Sbms { 600146768Ssam /* 601146768Ssam * Traditional Adapter 602146768Ssam */ 603190225Srpaulo /* 604190225Srpaulo * If the buffer size wasn't explicitly set, default to 605190225Srpaulo * WIN32_DEFAULT_USER_BUFFER_SIZE. 606190225Srpaulo */ 607190225Srpaulo if (p->opt.buffer_size == 0) 608190225Srpaulo p->opt.buffer_size = WIN32_DEFAULT_KERNEL_BUFFER_SIZE; 609190225Srpaulo 610190225Srpaulo if(PacketSetBuff(p->adapter,p->opt.buffer_size)==FALSE) 611190225Srpaulo { 612190225Srpaulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer"); 613190225Srpaulo goto bad; 614190225Srpaulo } 615146768Ssam 616190225Srpaulo p->buffer = (u_char *)malloc(p->bufsize); 617146768Ssam if (p->buffer == NULL) 618146768Ssam { 619190225Srpaulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); 620146768Ssam goto bad; 621146768Ssam } 622146768Ssam 623146768Ssam PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize); 624146768Ssam 625146768Ssam /* tell the driver to copy the buffer only if it contains at least 16K */ 626146768Ssam if(PacketSetMinToCopy(p->adapter,16000)==FALSE) 627146768Ssam { 628190225Srpaulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s", pcap_win32strerror()); 629146768Ssam goto bad; 630146768Ssam } 631127664Sbms } 632146768Ssam else 633146768Ssam#ifdef HAVE_DAG_API 634127664Sbms { 635146768Ssam /* 636146768Ssam * Dag Card 637146768Ssam */ 638146768Ssam LONG status; 639146768Ssam HKEY dagkey; 640146768Ssam DWORD lptype; 641146768Ssam DWORD lpcbdata; 642146768Ssam int postype = 0; 643146768Ssam char keyname[512]; 644146768Ssam 645146768Ssam snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s", 646146768Ssam "SYSTEM\\CurrentControlSet\\Services\\DAG", 647190225Srpaulo strstr(_strlwr(p->opt.source), "dag")); 648146768Ssam do 649146768Ssam { 650146768Ssam status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &dagkey); 651146768Ssam if(status != ERROR_SUCCESS) 652146768Ssam break; 653146768Ssam 654146768Ssam status = RegQueryValueEx(dagkey, 655146768Ssam "PosType", 656146768Ssam NULL, 657146768Ssam &lptype, 658146768Ssam (char*)&postype, 659146768Ssam &lpcbdata); 660146768Ssam 661146768Ssam if(status != ERROR_SUCCESS) 662146768Ssam { 663146768Ssam postype = 0; 664146768Ssam } 665146768Ssam 666146768Ssam RegCloseKey(dagkey); 667146768Ssam } 668146768Ssam while(FALSE); 669146768Ssam 670146768Ssam 671146768Ssam p->snapshot = PacketSetSnapLen(p->adapter, snaplen); 672146768Ssam 673146768Ssam /* Set the length of the FCS associated to any packet. This value 674146768Ssam * will be subtracted to the packet length */ 675146768Ssam p->md.dag_fcs_bits = p->adapter->DagFcsLen; 676127664Sbms } 677146768Ssam#else 678146768Ssam goto bad; 679146768Ssam#endif /* HAVE_DAG_API */ 680146768Ssam 681190225Srpaulo PacketSetReadTimeout(p->adapter, p->md.timeout); 682146768Ssam 683146768Ssam#ifdef HAVE_DAG_API 684146768Ssam if(p->adapter->Flags & INFO_FLAG_DAG_CARD) 685146768Ssam { 686146768Ssam /* install dag specific handlers for read and setfilter */ 687146768Ssam p->read_op = pcap_read_win32_dag; 688146768Ssam p->setfilter_op = pcap_setfilter_win32_dag; 689146768Ssam } 690146768Ssam else 691146768Ssam { 692146768Ssam#endif /* HAVE_DAG_API */ 693146768Ssam /* install traditional npf handlers for read and setfilter */ 694146768Ssam p->read_op = pcap_read_win32_npf; 695146768Ssam p->setfilter_op = pcap_setfilter_win32_npf; 696146768Ssam#ifdef HAVE_DAG_API 697146768Ssam } 698146768Ssam#endif /* HAVE_DAG_API */ 699147894Ssam p->setdirection_op = NULL; /* Not implemented. */ 700147894Ssam /* XXX - can this be implemented on some versions of Windows? */ 701146768Ssam p->inject_op = pcap_inject_win32; 702127664Sbms p->set_datalink_op = NULL; /* can't change data link type */ 703127664Sbms p->getnonblock_op = pcap_getnonblock_win32; 704127664Sbms p->setnonblock_op = pcap_setnonblock_win32; 705127664Sbms p->stats_op = pcap_stats_win32; 706190225Srpaulo p->setbuff_op = pcap_setbuff_win32; 707190225Srpaulo p->setmode_op = pcap_setmode_win32; 708190225Srpaulo p->setmintocopy_op = pcap_setmintocopy_win32; 709190225Srpaulo p->cleanup_op = pcap_cleanup_win32; 710127664Sbms 711190225Srpaulo return (0); 712127664Sbmsbad: 713190225Srpaulo pcap_cleanup_win32(p); 714190225Srpaulo return (PCAP_ERROR); 715127664Sbms} 716127664Sbms 717190225Srpaulopcap_t * 718251129Sdelphijpcap_create_interface(const char *device, char *ebuf) 719190225Srpaulo{ 720190225Srpaulo pcap_t *p; 721127664Sbms 722190225Srpaulo if (strlen(device) == 1) 723190225Srpaulo { 724190225Srpaulo /* 725190225Srpaulo * It's probably a unicode string 726190225Srpaulo * Convert to ascii and pass it to pcap_create_common 727190225Srpaulo * 728190225Srpaulo * This wonderful hack is needed because pcap_lookupdev still returns 729190225Srpaulo * unicode strings, and it's used by windump when no device is specified 730190225Srpaulo * in the command line 731190225Srpaulo */ 732190225Srpaulo size_t length; 733190225Srpaulo char* deviceAscii; 734190225Srpaulo 735190225Srpaulo length = wcslen((wchar_t*)device); 736190225Srpaulo 737190225Srpaulo deviceAscii = (char*)malloc(length + 1); 738190225Srpaulo 739190225Srpaulo if (deviceAscii == NULL) 740190225Srpaulo { 741190225Srpaulo snprintf(ebuf, PCAP_ERRBUF_SIZE, "Malloc failed"); 742190225Srpaulo return NULL; 743190225Srpaulo } 744190225Srpaulo 745190225Srpaulo snprintf(deviceAscii, length + 1, "%ws", (wchar_t*)device); 746190225Srpaulo p = pcap_create_common(deviceAscii, ebuf); 747190225Srpaulo free(deviceAscii); 748190225Srpaulo } 749190225Srpaulo else 750190225Srpaulo { 751190225Srpaulo p = pcap_create_common(device, ebuf); 752190225Srpaulo } 753190225Srpaulo 754190225Srpaulo if (p == NULL) 755190225Srpaulo return (NULL); 756190225Srpaulo 757190225Srpaulo p->activate_op = pcap_activate_win32; 758190225Srpaulo return (p); 759190225Srpaulo} 760190225Srpaulo 761127664Sbmsstatic int 762146768Ssampcap_setfilter_win32_npf(pcap_t *p, struct bpf_program *fp) 763127664Sbms{ 764127664Sbms if(PacketSetBpf(p->adapter,fp)==FALSE){ 765146768Ssam /* 766146768Ssam * Kernel filter not installed. 767146768Ssam * XXX - fall back on userland filtering, as is done 768146768Ssam * on other platforms? 769146768Ssam */ 770127664Sbms snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Driver error: cannot set bpf filter: %s", pcap_win32strerror()); 771127664Sbms return (-1); 772127664Sbms } 773146768Ssam 774146768Ssam /* 775146768Ssam * Discard any previously-received packets, as they might have 776146768Ssam * passed whatever filter was formerly in effect, but might 777146768Ssam * not pass this filter (BIOCSETF discards packets buffered 778146768Ssam * in the kernel, so you can lose packets in any case). 779146768Ssam */ 780146768Ssam p->cc = 0; 781127664Sbms return (0); 782127664Sbms} 783127664Sbms 784146768Ssam/* 785146768Ssam * We filter at user level, since the kernel driver does't process the packets 786146768Ssam */ 787146768Ssamstatic int 788146768Ssampcap_setfilter_win32_dag(pcap_t *p, struct bpf_program *fp) { 789146768Ssam 790146768Ssam if(!fp) 791146768Ssam { 792146768Ssam strncpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf)); 793146768Ssam return -1; 794146768Ssam } 795146768Ssam 796146768Ssam /* Install a user level filter */ 797146768Ssam if (install_bpf_program(p, fp) < 0) 798146768Ssam { 799146768Ssam snprintf(p->errbuf, sizeof(p->errbuf), 800146768Ssam "setfilter, unable to install the filter: %s", pcap_strerror(errno)); 801146768Ssam return -1; 802146768Ssam } 803146768Ssam 804146768Ssam p->md.use_bpf = 0; 805146768Ssam 806146768Ssam return (0); 807146768Ssam} 808127664Sbms 809127664Sbmsstatic int 810127664Sbmspcap_getnonblock_win32(pcap_t *p, char *errbuf) 811127664Sbms{ 812127664Sbms /* 813127664Sbms * XXX - if there were a PacketGetReadTimeout() call, we 814127664Sbms * would use it, and return 1 if the timeout is -1 815127664Sbms * and 0 otherwise. 816127664Sbms */ 817127664Sbms return (p->nonblock); 818127664Sbms} 819127664Sbms 820127664Sbmsstatic int 821127664Sbmspcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf) 822127664Sbms{ 823127664Sbms int newtimeout; 824127664Sbms 825127664Sbms if (nonblock) { 826127664Sbms /* 827127664Sbms * Set the read timeout to -1 for non-blocking mode. 828127664Sbms */ 829127664Sbms newtimeout = -1; 830127664Sbms } else { 831127664Sbms /* 832127664Sbms * Restore the timeout set when the device was opened. 833127664Sbms * (Note that this may be -1, in which case we're not 834127664Sbms * really leaving non-blocking mode.) 835127664Sbms */ 836190225Srpaulo newtimeout = p->md.timeout; 837127664Sbms } 838127664Sbms if (!PacketSetReadTimeout(p->adapter, newtimeout)) { 839251129Sdelphij snprintf(errbuf, PCAP_ERRBUF_SIZE, 840127664Sbms "PacketSetReadTimeout: %s", pcap_win32strerror()); 841127664Sbms return (-1); 842127664Sbms } 843127664Sbms p->nonblock = (newtimeout == -1); 844127664Sbms return (0); 845127664Sbms} 846127664Sbms 847190225Srpaulo/*platform-dependent routine to add devices other than NDIS interfaces*/ 848190225Srpauloint 849190225Srpaulopcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) 850127664Sbms{ 851190225Srpaulo return (0); 852127664Sbms} 853