Watt-32 tcp/ip  2.2 dev-rel.10
winpkt.c
Go to the documentation of this file.
1 
32 #include <process.h>
33 #include <arpa/inet.h>
34 
35 #if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__)
36 #include <windowsx.h>
37 
38 #include "wattcp.h"
39 #include "strings.h"
40 #include "misc.h"
41 #include "timer.h"
42 #include "profile.h"
43 #include "sock_ini.h"
44 #include "language.h"
45 #include "pcconfig.h"
46 #include "pcdbug.h"
47 #include "pcstat.h"
48 #include "pcpkt.h"
49 
50 #include "win_dll.h"
51 #include "winpkt.h"
52 #include "ntddndis.h"
53 #include "packet32.h"
54 #include "swsvpkt.h"
55 
56 #if (defined(_DLL) && !defined(_MT)) && !defined(__LCC__)
57 #error This file must be compiled for threads
58 #endif
59 
60 #define AIR_ADAPTER ADAPTER /* for tikm being */
61 
62 /* Rewritten from <ntddndis.h>
63  */
64 #define ND_PHY_Unspecified 0
65 #define ND_PHY_WirelessLan 1
66 #define ND_PHY_CableModem 2
67 #define ND_PHY_PhoneLine 3
68 #define ND_PHY_PowerLine 4
69 #define ND_PHY_DSL 5
70 #define ND_PHY_FibreChannel 6
71 #define ND_PHY_1394 7
72 #define ND_PHY_WirelessWan 8
73 #define ND_PHY_Native802_11 9
74 #define ND_PHY_Bluetooth 10
75 #define ND_PHY_Infiniband 11
76 #define ND_PHY_WiMax 12
77 #define ND_PHY_UWB 13
78 #define ND_PHY_802_3 14
79 #define ND_PHY_802_5 15
80 #define ND_PHY_Irda 16
81 #define ND_PHY_WiredWAN 17
82 #define ND_PHY_WiredCoWan 18
83 #define ND_PHY_Other 19
84 
85 WORD _pktdevclass = PDCLASS_UNKNOWN;
86 WORD _pkt_ip_ofs = 0;
87 BOOL _pktserial = FALSE;
88 int _pkt_errno = 0;
89 int _pkt_rxmode = RXMODE_DEFAULT;
90 int _pkt_rxmode0 = -1;
92 char _pktdrvrname [MAX_VALUELEN+1] = "";
93 char _pktdrvr_descr [MAX_VALUELEN+1] = "";
94 
95 struct pkt_info *_pkt_inf = NULL;
96 
97 /* Determines size of work buffers of NPF kernel and PacketReceivePacket().
98  * It doesn't influence the size of thread queue yet.
99  */
100 static int pkt_num_rx_bufs = RX_BUFS;
101 
102 /* WinPcap/SwsVpkt doesn't keep a count of transmitted packets and errors.
103  * So we maintain these counters locally.
104  */
105 static DWORD num_tx_pkt = 0UL;
106 static DWORD num_tx_bytes = 0UL;
107 static DWORD num_tx_errors = 0UL;
108 static DWORD num_rx_pkt = 0UL;
109 static DWORD num_rx_bytes = 0UL;
110 static DWORD pkt_drop_cnt = 0UL;
111 static int pkt_txretries = 2;
112 static int thr_realtime = 0;
113 static BOOL thr_stopped = FALSE;
114 static BOOL config_pass_1_done = FALSE;
115 static char dump_fname [MAX_PATHLEN] = "$(TEMP)\\winpkt_dump.txt";
116 
117 #define NdisMediumNull -1
118 
119 static const struct search_list logical_media[] = {
120  { NdisMediumNull, "Unknown?" },
121  { NdisMedium802_3, "802.3" },
122  { NdisMedium802_5, "802.5" },
123  { NdisMediumFddi, "FDDI" },
124  { NdisMediumWan, "WAN" },
125  { NdisMediumLocalTalk, "LocalTalk" },
126  { NdisMediumDix, "DIX" },
127  { NdisMediumArcnetRaw, "ArcNet (raw)" },
128  { NdisMediumArcnet878_2, "ArcNet (878.2)" },
129  { NdisMediumAtm, "ATM" },
130  { NdisMediumWirelessWan, "WiFi" },
131  { NdisMediumIrda, "IrDA" },
132  { NdisMediumBpc, "BPC" }, // 11
133  { NdisMediumCoWan, "CoWan" }, // 12
134  { NdisMedium1394, "1394 FW" }, // 13
135  { NdisMediumInfiniBand, "Inf-band" }, // 14
136  { NdisMediumTunnel, "Tunnel" },
137  { NdisMediumNative802_11, "Native 802.11" },
138  { NdisMediumLoopback, "Loopback" },
139  { NdisMediumWiMAX, "WiMax" },
140  { NdisMediumIP, "IP" },
141  { NdisMediumCHDLC, "CHDLC" }, // -2 (Custom linktype)
142  { NdisMediumPPPSerial, "PPP-ser" }
143  };
144 
145 static const struct search_list phys_media[] = {
146  { ND_PHY_WirelessLan, "Wireless LAN" },
147  { ND_PHY_CableModem, "Cable" },
148  { ND_PHY_PhoneLine, "Phone" },
149  { ND_PHY_PowerLine, "PowerLine" },
150  { ND_PHY_DSL, "DSL" },
151  { ND_PHY_FibreChannel, "Fibre" },
152  { ND_PHY_1394, "IEEE1394" },
153  { ND_PHY_WirelessWan, "Wireless WAN" },
154  { ND_PHY_Native802_11, "802.11" },
155  { ND_PHY_Bluetooth, "Bluetooth" },
156  { ND_PHY_Infiniband, "Infiniband" },
157  { ND_PHY_WiMax, "Wi-Max" },
158  { ND_PHY_UWB, "UWB" },
159  { ND_PHY_802_3, "802.3" },
160  { ND_PHY_802_5, "80.25" },
161  { ND_PHY_Irda, "Irda" },
162  { ND_PHY_WiredWAN, "Wired WAN" },
163  { ND_PHY_WiredCoWan, "Wired CoWan" },
164  { ND_PHY_Other, "Other?" }
165  };
166 
167 static enum eth_init_result open_winpcap_adapter (const char *name);
168 static enum eth_init_result open_airpcap_adapter (const char *name);
169 static enum eth_init_result open_wanpacket_adapter (const char *name);
170 static enum eth_init_result open_swsvpkt_adapter (const char *name);
171 
172 static BOOL get_if_stat_swsvpkt (const struct SwsVpktUsr *usr, BOOL *is_up);
173 static BOOL get_perm_mac_address (void *mac);
174 static BOOL get_interface_mtu (DWORD *mtu);
175 static void show_link_details (void);
176 static void set_txmode (const char *value);
177 
178 static void swsvpkt_callback (struct SwsVpktUsr *, const void *, unsigned);
179 static DWORD __stdcall winpcap_recv_thread (void *arg);
180 
181 const char *winpkt_trace_func; /* the function being traced */
182 const char *winpkt_trace_file; /* .. and in which source file */
183 UINT winpkt_trace_line; /* .. and at what line */
184 UINT winpkt_trace_level = 0;
185 
186 #if defined(USE_DEBUG)
187  static FILE *trace_file;
188 
189  void winpkt_trace (const char *fmt, ...)
190  {
191  static DWORD start_tick = 0UL;
192  va_list args;
193 
194  WATT_ASSERT (config_pass_1_done);
195 
196  if (!trace_file)
197  return;
198 
199  if (!start_tick)
200  {
201  fputs ("dT [ms] File Line Function etc.\n---------------------------"
202  "----------------------------------------------------------\n", trace_file);
203  start_tick = GetTickCount();
204  }
205  ENTER_CRIT();
206 
207  fprintf (trace_file, "%6lu %-10s %4u %s(): ", GetTickCount() - start_tick,
208  winpkt_trace_file, winpkt_trace_line, winpkt_trace_func);
209  va_start (args, fmt);
210  vfprintf (trace_file, fmt, args);
211  fflush (trace_file);
212  if (ferror(trace_file))
213  {
214  TCP_CONSOLE_MSG (1, ("error writing dump file %s; %s\n",
215  dump_fname, strerror(errno)));
216  winpkt_trace_fclose();
217  }
218  LEAVE_CRIT();
219  va_end (args);
220  }
221 
222  void winpkt_trace_fclose (void)
223  {
224  if (trace_file)
225  fclose (trace_file);
226  trace_file = NULL;
227  }
228 #endif
229 
233 static BOOL parse_config_pass_1 (void)
234 {
235  static const struct config_table pkt_init_cfg[] = {
236  { "WINPKT.DEVICE", ARG_STRCPY, (void*)&_pktdrvrname },
237  { "WINPKT.DUMPFILE", ARG_STRCPY, (void*)&dump_fname },
238  { "WINPKT.TRACE", ARG_ATOI, (void*)&winpkt_trace_level },
239  { "WINPKT.TXRETRIES",ARG_ATOB, (void*)&pkt_txretries },
240  { "WINPKT.TXMODE", ARG_FUNC, (void*)&set_txmode },
241  { "WINPKT.RXMODE", ARG_ATOX_W, (void*)&_pkt_forced_rxmode },
242  { "WINPKT.RXBUFS", ARG_ATOI, (void*)&pkt_num_rx_bufs },
243  { "WINPKT.HIGHPRIO", ARG_ATOI, (void*)&thr_realtime },
244  { NULL, 0, NULL }
245  };
246  const struct config_table *cfg_save = watt_init_cfg;
247  void (W32_CALL *init_save) (const char*, const char*) = usr_init;
248  int rc;
249 
250  watt_init_cfg = pkt_init_cfg;
251  usr_init = NULL; /* only pkt_init_cfg[] gets parsed */
252  rc = tcp_config (NULL);
253  usr_init = init_save;
254  watt_init_cfg = cfg_save;
255  config_pass_1_done = 1;
256  return (rc > 0);
257 }
258 
263 static BOOL find_winpcap_adapter (char *aname, size_t size)
264 {
265  const ADAPTER_INFO *ai;
266  int i;
267 
268  for (ai = PacketGetAdInfo(); ai; ai = ai->Next)
269  {
270  for (i = 0; i < ai->NNetworkAddresses; i++)
271  {
272  const npf_if_addr *if_addr = ai->NetworkAddresses + i;
273  const struct sockaddr_in *ip_addr = (const struct sockaddr_in*) &if_addr->IPAddress;
274 
275  if (ip_addr->sin_family == AF_INET)
276  {
277  _strlcpy (aname, ai->Name, size);
278  return (TRUE);
279  }
280  }
281  }
282  return (FALSE);
283 }
284 
285 /*
286  * Loop through "\\.\SwsVpkt<0-31>" and return TRUE on 1st available
287  * device.
288  */
289 static BOOL find_swsvpkt_adapter (char *aname, size_t size)
290 {
291  char name [sizeof("\\\\.\\SwsVpktXX")];
292  BOOL found;
293  int i;
294 
295  for (i = 0, found = FALSE; i <= 31 && !found; i++)
296  {
297  struct SwsVpktUsr *sw_usr;
298  struct SwsVpktOpenInfo sw_open;
299  struct SwsVpktAdapterState sw_state;
300 
301  memset (&sw_state,'\0', sizeof(sw_state));
302  sprintf (name, "\\\\.\\SwsVpkt%d", i);
303  sw_open.uRxBufs = pkt_num_rx_bufs;
304  sw_open.pfnRx = swsvpkt_callback;
305  sw_usr = SwsVpktOpen (name, &sw_open);
306  if (sw_usr)
307  {
308  get_if_stat_swsvpkt (sw_usr, &found);
309  SwsVpktClose (sw_usr);
310  }
311  }
312  if (found)
313  _strlcpy (aname, name, size);
314  return (found);
315 }
316 
322 static BOOL find_adapter (char *aname, size_t size)
323 {
324  BOOL rc;
325 
326  rc = find_winpcap_adapter (aname, size);
327  if (rc)
328  {
329  _eth_winpcap = TRUE;
330  return (TRUE);
331  }
332  rc = find_swsvpkt_adapter (aname, size);
333  if (rc)
334  {
335  _eth_SwsVpkt = TRUE;
336  return (TRUE);
337  }
338 #if 0
339  rc = find_airpcap_adapter (aname, size);
340  if (rc)
341  {
342  _eth_airpcap = TRUE;
343  return (TRUE);
344  }
345 #endif
346  return (rc);
347 }
348 
349 
350 /*
351  * Check receive-mode 'bits' for an illegal bit by turning all
352  * legal bits off.
353  */
354 static BOOL legal_recv_mode (WORD bits)
355 {
356  if (bits & RXMODE_OFF)
357  bits &= ~RXMODE_OFF;
358 
359  if (bits & RXMODE_DIRECT)
360  bits &= ~RXMODE_DIRECT;
361 
362  if (bits & RXMODE_MULTICAST1)
363  bits &= ~RXMODE_MULTICAST1;
364 
365  if (bits & RXMODE_MULTICAST2)
366  bits &= ~RXMODE_MULTICAST2;
367 
368  if (bits & RXMODE_BROADCAST)
369  bits &= ~RXMODE_BROADCAST;
370 
371  if (bits & RXMODE_PROMISCOUS)
372  bits &= ~RXMODE_PROMISCOUS;
373 
374  if (bits & RXMODE_ALL_LOCAL)
375  bits &= ~RXMODE_ALL_LOCAL;
376 
377  return (bits == 0);
378 }
379 
380 
385 int W32_CALL pkt_eth_init (mac_address *mac_addr)
386 {
387  enum eth_init_result rc;
388  DWORD thread_id;
389  BOOL is_up;
390  char descr [512];
391 
392  if (_watt_is_win9x)
393  {
394  (*_printf) (_LANG("Only Win-NT+ is supported.\n"));
395  _pkt_errno = PDERR_GEN_FAIL;
396  return (WERR_ILL_DOSX);
397  }
398 
399  if (!_watt_no_config || _watt_user_config_fn)
401 
402  _pkt_inf = calloc (sizeof(*_pkt_inf), 1);
403  if (!_pkt_inf)
404  {
405  (*_printf) (_LANG("Failed to allocate DRIVER data.\n"));
406  _pkt_errno = PDERR_GEN_FAIL;
407  return (WERR_NO_MEM);
408  }
409 
410 #if defined(USE_DEBUG)
411  if (winpkt_trace_level > 0 && dump_fname[0])
412  {
413  const char *file = expand_var_str (dump_fname);
414 
415  _strlcpy (dump_fname, file, sizeof(dump_fname));
416  trace_file = fopen_excl (file, "w+t");
417  }
418 #endif
419 
420  _eth_SwsVpkt = (strnicmp(_pktdrvrname,"\\\\.\\SwsVpkt",11) == 0);
421  _eth_airpcap = (strnicmp(_pktdrvrname,"\\\\.\\airpcap",11) == 0);
422  _eth_winpcap = (strnicmp(_pktdrvrname,"\\Device\\NPF_{",13) == 0);
423 
424  if (_eth_winpcap && !PacketInitModule())
425  {
426  (*_printf) (_LANG("Failed to initialise WinPcap.\n"));
427  pkt_release();
428  _pkt_errno = PDERR_NO_DRIVER;
429  return (WERR_PKT_ERROR);
430  }
431 
432  if (!_pktdrvrname[0] && !find_adapter(_pktdrvrname,sizeof(_pktdrvrname)))
433  {
434  (*_printf) (_LANG("No WinPcap or SwsVpkt driver found.\n"));
435  _pkt_errno = PDERR_NO_DRIVER;
436  return (WERR_NO_DRIVER);
437  }
438 
439  TCP_CONSOLE_MSG (2, ("device %s\n", _pktdrvrname));
440 
441  rc = _eth_SwsVpkt ? open_swsvpkt_adapter (_pktdrvrname) :
442  _eth_airpcap ? open_airpcap_adapter (_pktdrvrname) :
443  _eth_wanpacket ? open_wanpacket_adapter (_pktdrvrname) :
444  open_winpcap_adapter (_pktdrvrname);
445 
446  if (rc != WERR_NO_ERROR)
447  {
448  pkt_release();
449  return (rc);
450  }
451 
452  if (_pkt_inf->get_descr_op &&
453  (*_pkt_inf->get_descr_op)(_pkt_inf->adapter, descr, sizeof(descr)))
454  _strlcpy (_pktdrvr_descr, strrtrim(descr), sizeof(_pktdrvr_descr));
455 
456  if (!_pkt_inf->get_if_type_op ||
457  !(*_pkt_inf->get_if_type_op)(_pkt_inf->adapter, &_pktdevclass))
458  {
459  (*_printf) (_LANG("Failed to get interface type.\n"));
460  pkt_release();
461  return (WERR_PKT_ERROR);
462  }
463 
464  if (_pkt_inf->get_if_stat_op &&
465  (*_pkt_inf->get_if_stat_op) (_pkt_inf->adapter, &is_up) && !is_up)
466  (*_printf) (_LANG("Warning: the adapter %s is down\n"), _pktdrvrname);
467 
468  switch (_pktdevclass)
469  {
470  case PDCLASS_TOKEN:
471  _pkt_ip_ofs = sizeof(tok_Header);
472  break;
473  case PDCLASS_ETHER:
474  _pkt_ip_ofs = sizeof(eth_Header);
475  break;
476  case PDCLASS_FDDI:
477  _pkt_ip_ofs = sizeof(fddi_Header);
478  break;
479  case PDCLASS_ARCNET:
480  _pkt_ip_ofs = ARC_HDRLEN;
481  break;
482  default:
483  pkt_release();
484  (*_printf) (_LANG("WinPkt-ERROR: Unsupported driver class %dh\n"),
485  _pktdevclass);
486  _pkt_errno = PDERR_NO_CLASS;
487  return (WERR_PKT_ERROR);
488  }
489 
490  if (!pkt_get_addr(mac_addr)) /* get our MAC address */
491  {
492  pkt_release();
493  return (WERR_PKT_ERROR);
494  }
495 
496  pktq_init (&_pkt_inf->pkt_queue,
497  sizeof(_pkt_inf->rx_buf[0]), /* RX_SIZE */
498  DIM(_pkt_inf->rx_buf), /* RX_BUFS */
499  (char*)&_pkt_inf->rx_buf);
500 
501  if (_eth_winpcap) /* to-do: do this in 'open_XX_adapter' */
502  {
503  _pkt_inf->npf_buf_size = RX_SIZE * pkt_num_rx_bufs;
504  _pkt_inf->npf_buf = malloc (_pkt_inf->npf_buf_size);
505  if (!_pkt_inf->npf_buf)
506  {
507  (*_printf) (_LANG("Failed to allocate %d byte Rx buffer.\n"),
508  _pkt_inf->npf_buf_size);
509  pkt_release();
510  _pkt_errno = PDERR_GEN_FAIL;
511  return (WERR_NO_MEM);
512  }
513 
514  PacketSetLoopbackBehavior (_pkt_inf->adapter, NPF_DISABLE_LOOPBACK);
515  PacketSetMode (_pkt_inf->adapter, PACKET_MODE_CAPT);
516  PacketSetBuff (_pkt_inf->adapter, _pkt_inf->npf_buf_size);
517  PacketSetMinToCopy (_pkt_inf->adapter, ETH_MIN);
518 
519  /* PacketReceivePacket() blocks until something is received
520  */
521  PacketSetReadTimeout ((ADAPTER*)_pkt_inf->adapter, 0);
522  }
523 
524  /* Check Rx-mode from config-file.
525  */
526  if (_pkt_forced_rxmode != -1)
527  {
528  _pkt_forced_rxmode &= 0xFFFF; /* clear bits not set via ARG_ATOX_W */
529  if (_pkt_forced_rxmode == 0 || !legal_recv_mode(_pkt_forced_rxmode))
530  {
531  CONSOLE_MSG (0, ("Illegal Rx-mode (0x%02X) specified. Forcing default mode (0x%02X).\n",
532  _pkt_forced_rxmode, RXMODE_DEFAULT));
533  _pkt_forced_rxmode = RXMODE_DEFAULT;
534  }
535  }
536 
537  if (pkt_get_rcv_mode())
539 
540  /* Set Rx-mode; default or forced via config.
541  */
542  if (_pkt_forced_rxmode != -1)
543  pkt_set_rcv_mode (_pkt_forced_rxmode);
544  else pkt_set_rcv_mode (RXMODE_DEFAULT);
545 
546  if (_eth_winpcap || _eth_airpcap) /* to-do: do this in 'open_XX_adapter' */
547  {
548  _pkt_inf->recv_thread = CreateThread (NULL, 2048, winpcap_recv_thread,
549  NULL, 0, &thread_id);
550  if (!_pkt_inf->recv_thread)
551  {
552  (*_printf) (_LANG("Failed to create receiver thread; %s\n"),
553  win_strerror(GetLastError()));
554  pkt_release();
555  _pkt_errno = PDERR_GEN_FAIL;
556  return (WERR_PKT_ERROR);
557  }
558 
559  if (thr_realtime)
560  SetThreadPriority (_pkt_inf->recv_thread,
561  THREAD_PRIORITY_TIME_CRITICAL);
562 
563  CONSOLE_MSG (2, ("capture thread-id %lu\n", thread_id));
564  }
565 
566 #if defined(USE_DEBUG)
567  if (winpkt_trace_level >= 3)
568  {
569  (*_printf) ("link-details:\n");
570  show_link_details();
571  }
572 #endif
573 
574  return (0);
575 }
576 
577 int W32_CALL pkt_release (void)
578 {
579  ADAPTER *adapter;
580  DWORD status = 1;
581 
582  if (!_pkt_inf || _watt_fatal_error)
583  return (0);
584 
585  adapter = (ADAPTER*) _pkt_inf->adapter;
586 
587  TCP_CONSOLE_MSG (2, ("pkt_release(): adapter 0x%" ADDR_FMT "\n",
588  ADDR_CAST(adapter)));
589 
590  if (adapter && adapter != INVALID_HANDLE_VALUE)
591  {
592  /* Don't close the adapter before telling the thread about it.
593  * Only WinPcap/AirPcap devices have a receiver thread here.
594  */
595  if (_pkt_inf->recv_thread)
596  {
597  _pkt_inf->stop_thread = TRUE;
598  SetEvent (adapter->ReadEvent);
599  Sleep (50);
600 
601  GetExitCodeThread (_pkt_inf->recv_thread, &status);
602  if (status == STILL_ACTIVE)
603  TCP_CONSOLE_MSG (2, ("pkt_release(): killing thread.\n"));
604  else TCP_CONSOLE_MSG (2, ("pkt_release(): thread exit code %lu.\n",
605  status));
606 
607  print_thread_times (_pkt_inf->recv_thread);
608  TerminateThread (_pkt_inf->recv_thread, 1);
609  CloseHandle (_pkt_inf->recv_thread);
610  }
611 
612  (*_pkt_inf->close_op) ((void*)_pkt_inf->adapter);
613  _pkt_inf->adapter = NULL;
614  }
615 
616  if (_eth_winpcap)
617  DO_FREE (_pkt_inf->npf_buf);
618  DO_FREE (_pkt_inf);
619 
620  if (_eth_winpcap)
621  PacketExitModule();
622 
623 #if defined(USE_DEBUG)
624  winpkt_trace_fclose();
625 #endif
626 
627  return (int) status;
628 }
629 
630 /*
631  * Return the MAC address.
632  */
633 int W32_CALL pkt_get_addr (mac_address *eth)
634 {
635  mac_address mac;
636 
637  if (get_perm_mac_address(&mac))
638  {
639  memcpy (eth, &mac, sizeof(*eth));
640  return (1);
641  }
642  TCP_CONSOLE_MSG (2, ("Failed to get our MAC address; %s\n",
643  win_strerror(GetLastError())));
644  return (0);
645 }
646 
647 int W32_CALL pkt_set_addr (const void *eth)
648 {
649  ARGSUSED (eth);
650  return (0);
651 }
652 
653 /* Return TRUE is adapter is up.
654  */
655 BOOL W32_CALL pkt_is_init (void)
656 {
657  return (_pkt_inf != NULL);
658 }
659 
660 /*
661  * Check 'my_ip' against the IPv4 address(es) Winsock is using for
662  * this adapter. Only applies to WinPcap adapters.
663  */
664 BOOL W32_CALL pkt_check_address (DWORD my_ip)
665 {
666  const ADAPTER_INFO *ai;
667  int i;
668 
669  if (!_pkt_inf || !_pkt_inf->adapter_info)
670  return (TRUE);
671 
672  ai = (const ADAPTER_INFO*) _pkt_inf->adapter_info;
673 
674  for (i = 0; i < ai->NNetworkAddresses; i++)
675  {
676  const npf_if_addr *if_addr = ai->NetworkAddresses + i;
677  const struct sockaddr_in *ip_addr = (const struct sockaddr_in*) &if_addr->IPAddress;
678 
679  if (ntohl(ip_addr->sin_addr.s_addr) == my_ip)
680  return (FALSE);
681  }
682  return (TRUE); /* Okay, no possible conflict */
683 }
684 
685 
686 int W32_CALL pkt_buf_wipe (void)
687 {
688  if (_pkt_inf)
689  pktq_clear (&_pkt_inf->pkt_queue);
690  return (1);
691 }
692 
693 int W32_CALL pkt_waiting (void)
694 {
695  if (_pkt_inf)
696  return pktq_queued (&_pkt_inf->pkt_queue);
697  return (-1);
698 }
699 
700 void W32_CALL pkt_free_pkt (const void *pkt)
701 {
702  struct pkt_ringbuf *q;
703  const char *q_tail;
704  int delta;
705 
706  if (!_pkt_inf || !pkt)
707  return;
708 
709  q = &_pkt_inf->pkt_queue;
710  pkt_drop_cnt = q->num_drop;
711 
712  q_tail = (const char*)pkt - _pkt_ip_ofs - RX_ELEMENT_HEAD_SIZE;
713  delta = q_tail - pktq_out_buf (q);
714  if (delta)
715  {
716  TCP_CONSOLE_MSG (0, ("%s: freeing illegal packet 0x%p, delta %d.\n",
717  __FILE__, pkt, delta));
718  pktq_clear (q);
719  }
720  else
721  pktq_inc_out (q);
722 }
723 
727 static void set_txmode (const char *value)
728 {
729  ARGSUSED (value);
730 }
731 
754 static DWORD __stdcall winpcap_recv_thread (void *arg)
755 {
756  int rc = 0;
757 
758  while (1)
759  {
760  const struct bpf_hdr *bp;
761  BYTE *pkt, *pkt_end;
762  size_t pkt_len, cap_len, hdr_len;
763  UINT total_len, chunk;
764 
765  if (!_pkt_inf || _pkt_inf->stop_thread) /* this signals closure */
766  {
767  rc = 1;
768  break;
769  }
770 
771  pkt_len = _pkt_inf->npf_buf_size;
772  pkt = _pkt_inf->npf_buf;
773 
774  total_len = (*_pkt_inf->recv_op) (_pkt_inf->adapter, pkt, pkt_len);
775  if (total_len <= sizeof(*bp))
776  {
777  rc = 2;
778  break;
779  }
780 
781  ENTER_CRIT();
782 
783  for (pkt_end = pkt + total_len, chunk = 1;
784  pkt < pkt_end;
785  pkt += Packet_WORDALIGN(cap_len+hdr_len), chunk++)
786  {
787  struct pkt_ringbuf *q;
788  struct pkt_rx_element *head;
789 
790  q = &_pkt_inf->pkt_queue;
791  bp = (struct bpf_hdr*) pkt;
792 
793  cap_len = bp->bh_caplen;
794  hdr_len = bp->bh_hdrlen;
795 
796  TCP_CONSOLE_MSG (2, ("winpcap_recv_thread(): total_len %d, "
797  "chunk %d, cap_len %d, hdr_len %d, in-idx %d\n",
798  total_len, chunk, (int)cap_len, (int)hdr_len,
799  q->in_index));
800 
801  num_rx_bytes += total_len - sizeof(*bp);
802  num_rx_pkt++;
803 
804  if (cap_len > ETH_MAX)
805  {
806  _pkt_inf->error = "Large size";
807  STAT (macstats.num_too_large++);
808  }
809  else if (pktq_in_index(q) == q->out_index) /* queue is full, drop it */
810  q->num_drop++;
811  else
812  {
813  int pad_len, buf_max;
814 
815  head = (struct pkt_rx_element*) pktq_in_buf (q);
816  memcpy (head->rx_buf, pkt + hdr_len, cap_len);
817 
818  /* The NPF.SYS timestamp is very unrealiable. So we simply use
819  * QueryPerformanceCounter() as it is now.
820  */
821  head->tstamp_put = win_get_perf_count();
822  head->rx_length = cap_len;
823 
824  /* zero-pad up to ETH_MAX (don't destroy marker at end)
825  */
826  buf_max = q->buf_size - RX_ELEMENT_HEAD_SIZE - 4;
827  pad_len = min (ETH_MAX, buf_max - cap_len);
828  if (pad_len > 0)
829  memset (&head->rx_buf[cap_len], 0, pad_len);
830  pktq_inc_in (q);
831  }
832  }
833  LEAVE_CRIT();
834  }
835 
836  TCP_CONSOLE_MSG (2, ("winpcap_recv_thread(): rc %d\n", rc));
837  fflush (stdout);
838  ARGSUSED (arg);
839  thr_stopped = TRUE;
840  return (rc);
841 }
842 
846 static void swsvpkt_callback (struct SwsVpktUsr *usr, const void *buf, unsigned len)
847 {
848  struct pkt_ringbuf *q;
849  struct pkt_rx_element *head;
850 
851  q = &_pkt_inf->pkt_queue;
852 
853  ENTER_CRIT();
854 
855  TCP_CONSOLE_MSG (2, ("swsvpkt_callback(): len %d, in-idx %d\n",
856  len, q->in_index));
857 
858  if (len > ETH_MAX)
859  {
860  _pkt_inf->error = "Large size";
861  STAT (macstats.num_too_large++);
862  }
863  else if (pktq_in_index(q) == q->out_index) /* queue is full, drop it */
864  {
865  q->num_drop++;
866  TCP_CONSOLE_MSG (2, ("swsvpkt_callback(): num_drop %lu\n", q->num_drop));
867  }
868  else
869  {
870  int pad_len, buf_max;
871 
872  head = (struct pkt_rx_element*) pktq_in_buf (q);
873  memcpy (head->rx_buf, buf, len);
874  head->rx_length = len;
875  head->tstamp_put = win_get_perf_count();
876 
877  /* zero-pad up to ETH_MAX (don't destroy marker at end)
878  */
879  buf_max = q->buf_size - RX_ELEMENT_HEAD_SIZE - 4;
880  pad_len = min (ETH_MAX, buf_max - len);
881  if (pad_len > 0)
882  memset (&head->rx_buf[len], 0, pad_len);
883  pktq_inc_in (q);
884  }
885  ARGSUSED (usr);
886  LEAVE_CRIT();
887 }
888 
889 /*
890  * Poll the tail of queue
891  */
892 struct pkt_rx_element *pkt_poll_recv (void)
893 {
894  struct pkt_ringbuf *q;
895  struct pkt_rx_element *rc = NULL;
896  const char *out;
897  BOOL empty;
898 
899  if (!_pkt_inf)
900  return (NULL);
901 
902 #if 0
903  {
904  DWORD status = 0;
905 
906  GetExitCodeThread (_pkt_inf->recv_thread, &status);
907  if (status != STILL_ACTIVE && !thr_stopped)
908  {
909  TCP_CONSOLE_MSG (2, ("winpcap_recv_thread() is dead. status: %lXh\n",
910  status));
911  _pkt_inf->thread_stopped = 1;
912  Sleep (100);
913  }
914  }
915 #endif
916 
917  ENTER_CRIT();
918 
919  q = &_pkt_inf->pkt_queue;
920  out = pktq_out_buf (q);
921  empty = (q->in_index == q->out_index);
922 
923  LEAVE_CRIT();
924 
925  if (!empty)
926  {
927  rc = (struct pkt_rx_element*) out;
928  rc->tstamp_get = win_get_perf_count();
929  }
930  return (rc);
931 }
932 
933 /*
934  * Our WinPcap/SwsVpkt send function.
935  * Not sure if partial writes are possible with NPF. Retry if rc != length.
936  */
937 int W32_CALL pkt_send (const void *tx, int length)
938 {
939  int tx_cnt, rc = 0;
940 
941  ASSERT_PKT_INF (0);
942 
943  PROFILE_START ("pkt_send");
944 
945  for (tx_cnt = 1 + pkt_txretries; tx_cnt > 0; tx_cnt--)
946  {
947 #if 1
948  WATT_ASSERT (_pkt_inf->send_op);
949  rc = (*_pkt_inf->send_op) (_pkt_inf->adapter, tx, length);
950  if (rc == length)
951  break;
952 #else
953  struct SwsVpktUsr *sws_usr = (struct SwsVpktUsr*)_pkt_inf->adapter;
954  const ADAPTER *adapter = (const ADAPTER*)_pkt_inf->adapter;
955 
956  if (_eth_SwsVpkt ? SwsVpktSend(sws_usr, tx, length) :
957  // _eth_airpcap ? AirpcapWrite(air_adapter, tx, length) :
958  PacketSendPacket(adapter, tx, length))
959  {
960  rc = length;
961  break;
962  }
963 #endif
964  STAT (macstats.num_tx_retry++);
965  }
966 
967  if (rc == length)
968  {
969  num_tx_pkt++;
970  num_tx_bytes += length;
971  }
972  else
973  {
974  num_tx_errors++; /* local copy */
975  STAT (macstats.num_tx_err++);
976  }
977  PROFILE_STOP();
978  return (rc);
979 }
980 
981 /*
982  * Sets the receive mode of the WinPcap interface.
983  */
984 int W32_CALL pkt_set_rcv_mode (int mode)
985 {
986  struct {
987  PACKET_OID_DATA oidData;
988  DWORD filter;
989  } oid;
990  BOOL rc;
991  const ADAPTER *adapter;
992 
993  if (!_pkt_inf || _eth_SwsVpkt || _eth_airpcap)
994  return (0);
995 
996  adapter = (const ADAPTER*) _pkt_inf->adapter;
997 
998  memset (&oid, 0, sizeof(oid));
999  oid.oidData.Oid = OID_GEN_CURRENT_PACKET_FILTER;
1000  oid.oidData.Length = sizeof(oid.filter);
1001  *(DWORD*)oid.oidData.Data = mode;
1002  rc = PacketRequest (adapter, TRUE, &oid.oidData);
1003  if (rc)
1004  _pkt_rxmode = mode;
1005  else _pkt_errno = GetLastError();
1006 
1007  TCP_CONSOLE_MSG (2, ("pkt_set_rcv_mode(); mode 0x%02X, rc %d; %s\n",
1008  mode, rc, !rc ? win_strerror(GetLastError()) : "okay"));
1009  return (rc);
1010 }
1011 
1012 /*
1013  * Gets the receive mode of the WinPcap interface.
1014  * \retval !0 Okay - _pkt_errno = 0, _pkt_rxmode and retval is current mode.
1015  * \retval 0 Error - _pkt_errno = GetLastError().
1016  */
1017 int W32_CALL pkt_get_rcv_mode (void)
1018 {
1019  struct {
1020  PACKET_OID_DATA oidData;
1021  DWORD filter;
1022  } oid;
1023  DWORD mode;
1024  BOOL rc;
1025  const ADAPTER *adapter;
1026 
1027  if (!_pkt_inf || _eth_SwsVpkt || _eth_airpcap)
1028  return (0);
1029 
1030  adapter = (const ADAPTER*) _pkt_inf->adapter;
1031 
1032  memset (&oid, 0, sizeof(oid));
1033  oid.oidData.Oid = OID_GEN_CURRENT_PACKET_FILTER;
1034  oid.oidData.Length = sizeof(oid.filter);
1035  rc = PacketRequest (adapter, FALSE, &oid.oidData);
1036  mode = *(DWORD*)oid.oidData.Data;
1037  if (rc)
1038  _pkt_rxmode = mode;
1039  else _pkt_errno = GetLastError();
1040  return (rc);
1041 }
1042 
1043 static BOOL get_stats_pcap (const ADAPTER *adapter,
1044  struct PktStats *stats,
1045  struct PktStats *total)
1046 {
1047  struct {
1048  PACKET_OID_DATA oidData;
1049  DWORD value;
1050  } oid;
1051  struct bpf_stat b_stats;
1052  DWORD count[4];
1053 
1054  memset (total, 0, sizeof(*total)); /* we don't know yet */
1055  memset (&count, 0, sizeof(count));
1056 
1057  if (!PacketGetStatsEx(adapter,&b_stats))
1058  return (FALSE);
1059 
1060  /* Query: OID_GEN_RCV_OK, OID_GEN_RCV_ERROR
1061  * OID_GEN_XMIT_OK, OID_GEN_XMIT_ERROR
1062  */
1063  memset (&oid, 0, sizeof(oid));
1064  oid.oidData.Oid = OID_GEN_RCV_OK;
1065  oid.oidData.Length = sizeof(oid.value);
1066  if (!PacketRequest (adapter, FALSE, &oid.oidData))
1067  goto no_total;
1068  count[0] = *(DWORD*) &oid.oidData.Data;
1069 
1070  memset (&oid, 0, sizeof(oid));
1071  oid.oidData.Oid = OID_GEN_XMIT_OK;
1072  oid.oidData.Length = sizeof(oid.value);
1073  if (!PacketRequest (adapter, FALSE, &oid.oidData))
1074  goto no_total;
1075  count[1] = *(DWORD*) &oid.oidData.Data;
1076 
1077  memset (&oid, 0, sizeof(oid));
1078  oid.oidData.Oid = OID_GEN_RCV_ERROR;
1079  oid.oidData.Length = sizeof(oid.value);
1080  if (!PacketRequest (adapter, FALSE, &oid.oidData))
1081  goto no_total;
1082  count[2] = *(DWORD*) &oid.oidData.Data;
1083 
1084  memset (&oid, 0, sizeof(oid));
1085  oid.oidData.Oid = OID_GEN_XMIT_ERROR;
1086  oid.oidData.Length = sizeof(oid.value);
1087  if (!PacketRequest (adapter, FALSE, &oid.oidData))
1088  goto no_total;
1089  count[3] = *(DWORD*) &oid.oidData.Data;
1090 
1091 no_total:
1092  total->in_packets = count[0];
1093  total->out_packets = count[1];
1094  total->in_errors = count[2];
1095  total->out_errors = count[3];
1096 
1097  stats->in_packets = num_rx_pkt; /* !! b_stats.bs_recv */
1098  stats->in_bytes = num_rx_bytes;
1099  stats->out_packets = num_tx_pkt;
1100  stats->out_bytes = num_tx_bytes;
1101  stats->in_errors = 0UL;
1102  stats->out_errors = num_tx_errors;
1103  stats->lost = b_stats.bs_drop + b_stats.ps_ifdrop;
1104  return (TRUE);
1105 }
1106 
1107 static BOOL get_stats_swsvpkt (const struct SwsVpktUsr *usr,
1108  struct PktStats *stats,
1109  struct PktStats *total)
1110 {
1111  memset (stats, 0, sizeof(*stats));
1112  memset (total, 0, sizeof(*total)); /* not known */
1113  return SwsVpktGetStatistics (usr, stats);
1114 }
1115 
1116 /*
1117  * Return traffic statistics since started (stats) and
1118  * total since adapter was opened (total).
1119  *
1120  * \note 'stats' only count traffic we received and transmitted.
1121  */
1122 int W32_CALL pkt_get_stats (struct PktStats *stats, struct PktStats *total)
1123 {
1124  if (!_pkt_inf || !_pkt_inf->get_stats_op)
1125  return (0);
1126  return (*_pkt_inf->get_stats_op) (_pkt_inf->adapter,stats,total);
1127 }
1128 
1129 DWORD W32_CALL pkt_dropped (void)
1130 {
1131  if (_pkt_inf)
1132  return (_pkt_inf->pkt_queue.num_drop);
1133  return (pkt_drop_cnt); /* return last known value */
1134 }
1135 
1136 int W32_CALL pkt_get_mtu (void)
1137 {
1138  DWORD MTU;
1139 
1140  if (get_interface_mtu(&MTU))
1141  return (MTU);
1142  return (0);
1143 }
1144 
1145 const char * W32_CALL pkt_strerror (int code)
1146 {
1147  ARGSUSED (code);
1148 
1158  return (NULL);
1159 }
1160 
1161 #if defined(USE_MULTICAST)
1162 /*
1163  * Don't think we need to support this since we can use promiscous mode
1164  */
1165 int pkt_get_multicast_list (mac_address *listbuf, int *len)
1166 {
1167  _pkt_errno = PDERR_NO_MULTICAST;
1168  *len = 0;
1169  ARGSUSED (listbuf);
1170  ARGSUSED (len);
1171  return (0);
1172 }
1173 
1174 int pkt_set_multicast_list (const void *listbuf, int len)
1175 {
1176  _pkt_errno = PDERR_NO_MULTICAST;
1177  ARGSUSED (listbuf);
1178  ARGSUSED (len);
1179  return (0);
1180 }
1181 #endif
1182 
1183 
1184 /*
1185  * Low-level NDIS/Mini-driver functions.
1186  */
1187 static BOOL get_perm_mac_address (void *mac)
1188 {
1189  if (!_pkt_inf || !_pkt_inf->get_mac_op)
1190  return (FALSE);
1191  memset (mac, '\0', sizeof(mac_address));
1192  return (*_pkt_inf->get_mac_op) (_pkt_inf->adapter, mac);
1193 }
1194 
1195 static BOOL get_if_mtu_pcap (const ADAPTER *adapter, DWORD *mtu)
1196 {
1197  struct {
1198  PACKET_OID_DATA oidData;
1199  DWORD mtu;
1200  } oid;
1201 
1202  memset (&oid, 0, sizeof(oid));
1203  oid.oidData.Oid = OID_GEN_MAXIMUM_TOTAL_SIZE;
1204  oid.oidData.Length = sizeof(oid.mtu);
1205 
1206  if (!PacketRequest(adapter, FALSE, &oid.oidData))
1207  return (FALSE);
1208  *mtu = *(DWORD*) &oid.oidData.Data;
1209  return (TRUE);
1210 }
1211 
1212 static BOOL get_if_mtu_generic (const void *adapter, DWORD *mtu)
1213 {
1214  *mtu = ETH_MAX;
1215  return (TRUE);
1216 }
1217 
1218 static BOOL get_interface_mtu (DWORD *mtu)
1219 {
1220  if (!_pkt_inf || !_pkt_inf->get_if_mtu_op)
1221  return (FALSE);
1222  return (*_pkt_inf->get_if_mtu_op) (_pkt_inf->adapter, mtu);
1223 }
1224 
1225 static BOOL get_if_type_pcap (const ADAPTER *adapter, WORD *type)
1226 {
1227  struct {
1228  PACKET_OID_DATA oidData;
1229  DWORD link;
1230  } oid;
1231 
1232  memset (&oid, 0, sizeof(oid));
1233  oid.oidData.Oid = OID_GEN_MEDIA_IN_USE;
1234  oid.oidData.Length = sizeof(oid.link);
1235 
1236  if (!PacketRequest(adapter, FALSE, &oid.oidData))
1237  return (FALSE);
1238  *type = *(WORD*) &oid.oidData.Data;
1239  return (TRUE);
1240 }
1241 
1242 static BOOL get_if_type_swsvpkt (const struct SwsVpktUsr *usr, WORD *type)
1243 {
1244  *type = PDCLASS_ETHER;
1245  ARGSUSED (usr);
1246  return (TRUE);
1247 }
1248 
1249 static BOOL get_if_type_airpcap (const AIR_ADAPTER *adapter, WORD *type)
1250 {
1251  *type = PDCLASS_ETHER;
1252  ARGSUSED (adapter);
1253  return (TRUE);
1254 }
1255 
1256 /* Query the NIC driver for the adapter description
1257  */
1258 static BOOL get_descr_pcap (const ADAPTER *adapter, char *buf, size_t max)
1259 {
1260  struct {
1261  PACKET_OID_DATA oidData;
1262  char descr[512];
1263  } oid;
1264 
1265  memset (&oid, 0, sizeof(oid));
1266  oid.oidData.Oid = OID_GEN_VENDOR_DESCRIPTION;
1267  oid.oidData.Length = sizeof(oid.descr);
1268 
1269  if (!PacketRequest(adapter, FALSE, &oid.oidData))
1270  return (FALSE);
1271  strncpy (buf, (const char*)&oid.oidData.Data, max);
1272  return (TRUE);
1273 }
1274 
1275 static BOOL get_descr_swsvpkt (const struct SwsVpktUsr *usr, char *buf, size_t max)
1276 {
1277  return SwsVpktGetDescription (usr, buf, max);
1278 }
1279 
1280 static BOOL get_if_speed_pcap (const ADAPTER *adapter, DWORD *Mbit_s)
1281 {
1282  struct {
1283  PACKET_OID_DATA oidData;
1284  DWORD speed;
1285  } oid;
1286 
1287  memset (&oid, 0, sizeof(oid));
1288  oid.oidData.Oid = OID_GEN_LINK_SPEED;
1289  oid.oidData.Length = sizeof(oid.speed);
1290 
1291  if (!PacketRequest(adapter, FALSE, &oid.oidData))
1292  return (FALSE);
1293 
1294  *Mbit_s = (*(DWORD*)&oid.oidData.Data) / 10000;
1295  return (TRUE);
1296 }
1297 
1298 static BOOL get_if_speed_airpcap (const AIR_ADAPTER *adapter, DWORD *Mbit_s)
1299 {
1300  *Mbit_s = 54; /* fixed at 54MB/s? */
1301  ARGSUSED (adapter);
1302  return (TRUE);
1303 }
1304 
1305 #if defined(USE_DEBUG)
1306 static BOOL get_interface_speed (DWORD *speed)
1307 {
1308  if (!_pkt_inf || !_pkt_inf->get_if_speed_op)
1309  return (FALSE);
1310  return (*_pkt_inf->get_if_speed_op) (_pkt_inf->adapter, speed);
1311 }
1312 
1313 static BOOL get_phys_media (int *media)
1314 {
1315  struct {
1316  PACKET_OID_DATA oidData;
1317  DWORD media;
1318  } oid;
1319  const ADAPTER *adapter;
1320 
1321  if (!_pkt_inf || _eth_SwsVpkt || _eth_airpcap)
1322  return (FALSE);
1323 
1324  adapter = (const ADAPTER*) _pkt_inf->adapter;
1325  memset (&oid, 0, sizeof(oid));
1326  oid.oidData.Oid = OID_GEN_PHYSICAL_MEDIUM;
1327  oid.oidData.Length = sizeof(oid.media);
1328 
1329  if (!PacketRequest(adapter, FALSE, &oid.oidData))
1330  return (FALSE);
1331  *media = *(int*) &oid.oidData.Data;
1332  return (TRUE);
1333 }
1334 #endif
1335 
1336 static BOOL get_if_stat_pcap (const ADAPTER *adapter, BOOL *is_up)
1337 {
1338  struct {
1339  PACKET_OID_DATA oidData;
1340  DWORD connected;
1341  } oid;
1342 
1343  memset (&oid, 0, sizeof(oid));
1344  oid.oidData.Oid = OID_GEN_MEDIA_CONNECT_STATUS;
1345  oid.oidData.Length = sizeof(oid.connected);
1346 
1347  if (!PacketRequest(adapter, FALSE, &oid.oidData))
1348  return (FALSE);
1349  *is_up = (*(DWORD*)&oid.oidData.Data == NdisMediaStateConnected);
1350  return (TRUE);
1351 }
1352 
1353 static BOOL get_if_stat_swsvpkt (const struct SwsVpktUsr *usr, BOOL *is_up)
1354 {
1355  struct SwsVpktAdapterState state;
1356 
1357  memset (&state, '\0', sizeof(state));
1358  if (!SwsVpktGetAdapterState(usr,&state))
1359  return (FALSE);
1360 
1361  *is_up = (state.isMediaConnected) || (state.isWan && !state.isWanDown);
1362  return (TRUE);
1363 }
1364 
1365 #ifdef NOT_USED
1366 /*
1367  * NDIS has the annoying feature (?) of looping packets we send in
1368  * NDIS_PACKET_TYPE_ALL_LOCAL mode (the default?). Disable it, but
1369  * doesn't seem to have any effect yet. Maybe need to use a BPF filter?
1370  *
1371  * No need when using RXMODE_DEFAULT (9).
1372  */
1373 static BOOL ndis_set_loopback (BOOL enable)
1374 {
1375  struct {
1376  PACKET_OID_DATA oidData;
1377  DWORD options;
1378  } oid;
1379  const ADAPTER *adapter;
1380  BOOL rc;
1381  DWORD options;
1382  DWORD gen_oid = OID_GEN_MAC_OPTIONS;
1383  DWORD opt_bit = NDIS_MAC_OPTION_NO_LOOPBACK;
1384 
1385  if (!_pkt_inf || _eth_SwsVpkt || _eth_airpcap)
1386  return (FALSE);
1387 
1388  adapter = (const ADAPTER*) _pkt_inf->adapter;
1389  memset (&oid, 0, sizeof(oid));
1390  oid.oidData.Oid = gen_oid;
1391  oid.oidData.Length = sizeof(oid.options);
1392 
1393  /* Get current MAC/protocol options
1394  */
1395  rc = PacketRequest (adapter, FALSE, &oid.oidData);
1396  options = *(DWORD*) &oid.oidData.Data;
1397 
1398  TCP_CONSOLE_MSG (2, ("ndis_set_loopback(); rc %d, options 0x%02lX; %s\n",
1399  rc, options, !rc ? win_strerror(GetLastError()) : "okay"));
1400  if (enable)
1401  options &= ~opt_bit;
1402  else options |= opt_bit;
1403 
1404  /* Set it back
1405  */
1406  memset (&oid, 0, sizeof(oid));
1407  oid.oidData.Oid = gen_oid;
1408  oid.oidData.Length = sizeof(oid.options);
1409  *(DWORD*) &oid.oidData.Data = options;
1410  rc = PacketRequest (adapter, TRUE, &oid.oidData);
1411 
1412  TCP_CONSOLE_MSG (2, ("ndis_set_loopback(); rc %d; %s\n",
1413  rc, !rc ? win_strerror(GetLastError()) : "okay"));
1414  return (rc);
1415 }
1416 #endif /* NOT_USED */
1417 
1418 
1419 /*
1420  * Return NDIS version as MSB.LSB.
1421  */
1422 int W32_CALL pkt_get_api_ver (WORD *ver_p)
1423 {
1424  BOOL rc = FALSE;
1425 
1426  if (!_pkt_inf)
1427  return (0);
1428 
1429  if (_eth_SwsVpkt)
1430  {
1431  const struct SwsVpktUsr *sw_usr = _pkt_inf->adapter;
1432  DWORD ver = 0;
1433 
1434  rc = SwsVpktGetNDISversion (sw_usr, &ver); /* This IOCTL always seems to fail */
1435  if (rc)
1436  *ver_p = (WORD)ver;
1437  }
1438  else if (_eth_airpcap)
1439  {
1440  }
1441  else if (_eth_winpcap)
1442  {
1443  struct {
1444  PACKET_OID_DATA oidData;
1445  DWORD version;
1446  } oid;
1447  const ADAPTER *adapter = (const ADAPTER*) _pkt_inf->adapter;
1448 
1449  memset (&oid, 0, sizeof(oid));
1450  oid.oidData.Length = sizeof(oid.version);
1451  oid.oidData.Oid = OID_GEN_DRIVER_VERSION;
1452 
1453  rc = PacketRequest (adapter, FALSE, &oid.oidData);
1454  if (rc)
1455  {
1456  WORD ver = *(WORD*) &oid.oidData.Data; /* There's only 16-bit valid in version */
1457  *ver_p = ver;
1458  }
1459  }
1460  return (rc);
1461 }
1462 
1463 /*
1464  * Returns NPF.SYS/SwsVpkt.sys/airpcap.sys version as "major,minor,0,build" or
1465  * "major.minor.0.build" (8 bits each).
1466  */
1467 int W32_CALL pkt_get_drvr_ver (WORD *major, WORD *minor, WORD *unused, WORD *build)
1468 {
1469  const char *ver = (_pkt_inf && _pkt_inf->get_drv_ver_op) ?
1470  (*_pkt_inf->get_drv_ver_op)() : NULL;
1471  if (!ver)
1472  return (0);
1473 
1474  if (sscanf(ver, "%hu,%hu,%hu,%hu", major, minor, unused, build) == 4 ||
1475  sscanf(ver, "%hu.%hu.%hu.%hu", major, minor, unused, build) == 4)
1476  return (1);
1477  return (0);
1478 }
1479 
1480 /*
1481  * Returns name of driver; NPF.SYS/SwsVpkt.sys/airpcap.sys etc.
1482  */
1483 const char * W32_CALL pkt_get_drvr_name (void)
1484 {
1485  if (_pkt_inf)
1486  return (_pkt_inf->sys_drvr_name);
1487  return (NULL);
1488 }
1489 
1490 /*
1491  * Returns low-level device-name of driver; "\Device\NPF_{..."
1492  */
1493 const char * W32_CALL pkt_get_device_name (void)
1494 {
1495  return (_pktdrvrname);
1496 }
1497 
1498 /*
1499  * Return driver description
1500  */
1501 const char * W32_CALL pkt_get_drvr_descr (void)
1502 {
1503  return (_pktdrvr_descr);
1504 }
1505 
1506 /*
1507  * Return driver class
1508  */
1509 W32_FUNC WORD W32_CALL pkt_get_drvr_class (void)
1510 {
1511  return (_pktdevclass);
1512 }
1513 
1517 static enum eth_init_result open_winpcap_adapter (const char *name)
1518 {
1519  const ADAPTER *adapter = PacketOpenAdapter (name);
1520 
1521  if (!adapter)
1522  {
1523  (*_printf) (_LANG("PacketOpenAdapter (\"%s\") failed; %lu\n"),
1524  name, GetLastError());
1525  return (WERR_NO_DRIVER);
1526  }
1527 
1528  _pkt_inf->adapter = adapter;
1529  _pkt_inf->adapter_info = PacketFindAdInfo (name);
1530  _pkt_inf->init_op = PacketInitModule;
1531  _pkt_inf->close_op = (func_close) PacketCloseAdapter;
1532  _pkt_inf->send_op = (func_send) PacketSendPacket;
1533  _pkt_inf->recv_op = (func_recv) PacketReceivePacket;
1534  _pkt_inf->get_mac_op = (func_get_mac) PacketGetMacAddress;
1535  _pkt_inf->get_stats_op = (func_get_stats) get_stats_pcap;
1536  _pkt_inf->get_if_stat_op = (func_get_if_stat) get_if_stat_pcap;
1537  _pkt_inf->get_if_type_op = (func_get_if_type) get_if_type_pcap;
1538  _pkt_inf->get_if_speed_op = (func_get_if_speed) get_if_speed_pcap;
1539  _pkt_inf->get_if_mtu_op = (func_get_if_mtu) get_if_mtu_pcap;
1540  _pkt_inf->get_descr_op = (func_get_descr) get_descr_pcap;
1541  _pkt_inf->get_drv_ver_op = PacketGetDriverVersion;
1542  _pkt_inf->api_name = "WinPcap";
1543  _pkt_inf->sys_drvr_name = "NPF.sys";
1544 
1545  return (WERR_NO_ERROR);
1546 }
1547 
1551 static enum eth_init_result open_airpcap_adapter (const char *name)
1552 {
1554  (*_printf) ("adapter-name: %s\n", name);
1555  UNFINISHED();
1556 #if 0
1557  const AIR_ADAPTER *adapter = AirPcapOpen (name);
1558  _pkt_inf->adapter = adapter;
1559  _pkt_inf->send_op = AirpcapWrite;
1560  _pkt_inf->get_mac_op = AirpcapGetMacAddress;
1561  _pkt_inf->close_op = AirpcapClose;
1562 #endif
1563  _pkt_inf->get_if_mtu_op = (func_get_if_mtu) get_if_mtu_generic;
1564  _pkt_inf->get_if_speed_op = (func_get_if_speed) get_if_speed_airpcap;
1565  _pkt_inf->get_if_type_op = (func_get_if_type) get_if_type_airpcap;
1566 //_pkt_inf->get_drv_ver_op = AirpcapGetDriverVersion;
1567  _pkt_inf->api_name = "airpcap";
1568  _pkt_inf->sys_drvr_name = "airpcap.sys";
1569 
1570  return (WERR_NO_ERROR);
1571 }
1572 
1576 static enum eth_init_result open_wanpacket_adapter (const char *name)
1577 {
1578  WAN_ADAPTER *ad;
1579 
1581  (*_printf) ("adapter-name: %s\n", name);
1582 
1583  ad = WanPacketOpenAdapter();
1584  if (!ad)
1585  return (WERR_PKT_ERROR);
1586 
1587 #if 0 // !!
1588  if (ad)
1589  ad->flags = INFO_FLAG_NDISWAN_ADAPTER;
1590 #endif
1591 
1592  _pkt_inf->get_if_mtu_op = get_if_mtu_generic;
1593  _pkt_inf->get_drv_ver_op = NULL;
1594  _pkt_inf->api_name = "WanPacket";
1595  _pkt_inf->sys_drvr_name = "wanpacket.dll";
1596 
1597  return (WERR_NO_ERROR);
1598 }
1599 
1603 static enum eth_init_result open_swsvpkt_adapter (const char *name)
1604 {
1605  struct SwsVpktOpenInfo sw_open;
1606  const struct SwsVpktUsr *sw_usr;
1607 
1608  sw_open.uRxBufs = pkt_num_rx_bufs;
1609  sw_open.pfnRx = swsvpkt_callback;
1610  sw_usr = SwsVpktOpen (name, &sw_open);
1611  if (!sw_usr)
1612  {
1613  (*_printf) (_LANG("SwsVpktOpen (\"%s\") failed.\n"), name);
1614  return (WERR_NO_DRIVER);
1615  }
1616  _pkt_inf->adapter = sw_usr;
1617  _pkt_inf->send_op = (func_send) SwsVpktSend;
1618  _pkt_inf->close_op = (func_close) SwsVpktClose;
1619  _pkt_inf->get_mac_op = (func_get_mac) SwsVpktGetMacAddress;
1620  _pkt_inf->get_descr_op = (func_get_descr) get_descr_swsvpkt;
1621  _pkt_inf->get_stats_op = (func_get_stats) get_stats_swsvpkt;
1622  _pkt_inf->get_if_mtu_op = (func_get_if_mtu) get_if_mtu_generic;
1623  _pkt_inf->get_if_type_op = (func_get_if_type) get_if_type_swsvpkt;
1624  _pkt_inf->get_if_stat_op = (func_get_if_stat) get_if_stat_swsvpkt;
1625  _pkt_inf->get_drv_ver_op = SwsVpktGetDriverVersion;
1626  _pkt_inf->api_name = "SwsVpkt";
1627  _pkt_inf->sys_drvr_name = "SwsVpkt.sys";
1628 
1629  return (WERR_NO_ERROR);
1630 }
1631 
1632 
1633 /*
1634  * Show some WinPcap adapter details.
1635  * The IP-address, netmask etc. are what Winsock uses. We ignore
1636  * them and use what WATTCP.CFG specifies.
1637  */
1638 static void show_link_details (void)
1639 {
1640 #if defined(USE_DEBUG)
1641  const ADAPTER_INFO *ai;
1642  int i, phy;
1643  BOOL is_up;
1644  DWORD MTU, speed;
1645  WORD ver;
1646  mac_address mac;
1647 
1648  if (!_pkt_inf || !_pkt_inf->adapter_info)
1649  return;
1650 
1651  ai = (const ADAPTER_INFO*) _pkt_inf->adapter_info;
1652  if (!ai)
1653  {
1654  (*_printf) (" not available\n");
1655  return;
1656  }
1657 
1658  (*_printf) (" %d network address%s:\n",
1659  ai->NNetworkAddresses, ai->NNetworkAddresses > 1 ? "es" : "");
1660  for (i = 0; i < ai->NNetworkAddresses; i++)
1661  {
1662  const npf_if_addr *if_addr = ai->NetworkAddresses + i;
1663  const struct sockaddr_in *ip_addr = (const struct sockaddr_in*) &if_addr->IPAddress;
1664  const struct sockaddr_in *netmask = (const struct sockaddr_in*) &if_addr->SubnetMask;
1665  const struct sockaddr_in *brdcast = (const struct sockaddr_in*) &if_addr->Broadcast;
1666 
1667  (*_printf) (" IP-addr %s", inet_ntoa(ip_addr->sin_addr));
1668  (*_printf) (", netmask %s", inet_ntoa(netmask->sin_addr));
1669  (*_printf) (", broadcast %s\n", inet_ntoa(brdcast->sin_addr));
1670  }
1671  if (ai->NNetworkAddresses <= 0)
1672  (*_printf) ("\n");
1673 
1674  if (get_perm_mac_address(&mac))
1675  (*_printf) (" MAC-addr %s, ", MAC_address(&mac));
1676 
1677  if (get_interface_mtu(&MTU))
1678  (*_printf) ("MTU %lu, ", MTU);
1679 
1680  (*_printf) ("link-type %s, ",
1681  list_lookup(_pktdevclass, logical_media, DIM(logical_media)));
1682 
1683  if (get_phys_media(&phy))
1684  (*_printf) (" over %s, ", list_lookup(phy, phys_media, DIM(phys_media)));
1685 
1686  if (_pkt_inf->get_if_stat_op &&
1687  (*_pkt_inf->get_if_stat_op) (_pkt_inf->adapter, &is_up))
1688  (*_printf) ("%s, ", is_up ? "UP" : "DOWN");
1689 
1690  if (get_interface_speed(&speed))
1691  (*_printf) ("%luMb/s, ", speed);
1692 
1693  if (pkt_get_api_ver(&ver))
1694  (*_printf) ("NDIS %u.%u", hiBYTE(ver), loBYTE(ver));
1695  (*_printf) ("\n");
1696 #endif
1697 }
1698 #endif /* WIN32 || _WIN32 || __CYGWIN__ */
1699 
int W32_CALL pkt_set_addr(const void *eth)
Set a new MAC source address.
Definition: winpkt.c:647
convert to hex-word
Definition: tcp.h:429
convert to int
Definition: tcp.h:424
call convertion function
Definition: tcp.h:434
int pkt_set_multicast_list(const void *listbuf, int len)
Sets the list of multicast addresses for which the PKTDRVR is responsible.
Definition: winpkt.c:1174
BOOL _eth_winpcap
for Win32 using an WinPcap adapter (default)
Definition: pcsed.c:61
int W32_CALL pkt_get_stats(struct PktStats *stats, struct PktStats *total)
Get PKTDRVR statistics.
Definition: winpkt.c:1122
int _pkt_forced_rxmode
wattcp.cfg receive mode
Definition: winpkt.c:91
static enum eth_init_result open_airpcap_adapter(const char *name)
Open the named AirPcap device.
Definition: winpkt.c:1551
static BOOL get_if_type_swsvpkt(const struct SwsVpktUsr *usr, WORD *type)
Definition: winpkt.c:1242
BOOL _watt_no_config
run with no config file (embedded/diskless)
Definition: sock_ini.c:135
Addresses of a network adapter.
Definition: packet32.h:168
BOOL _eth_wanpacket
for Win32 using an WanPacket adapter
Definition: pcsed.c:60
static BOOL find_winpcap_adapter(char *aname, size_t size)
Traverse 'adapters_list' and select 1st device with an IPv4 address.
Definition: winpkt.c:263
NDIS_PACKET_TYPE_ALL_LOCAL (direct+bc+mc1)
Definition: winpkt.h:30
int W32_CALL pkt_get_drvr_ver(WORD *major, WORD *minor, WORD *unused, WORD *build)
Return version of PKTDRVR.
Definition: winpkt.c:1467
copy string value
Definition: tcp.h:432
DIRECT + broadcast packets.
Definition: pcpkt.h:111
static BOOL find_adapter(char *aname, size_t size)
Search for the first proper WinPcap or SwsVpkt device.
Definition: winpkt.c:322
int pkt_get_multicast_list(mac_address *listbuf, int *len)
Gets the current list of multicast addresses from the PKTDRVR.
Definition: winpkt.c:1165
char _pktdrvrname[MAX_VALUELEN+1]
Name of PKDRVR.
Definition: winpkt.c:92
static BOOL parse_config_pass_1(void)
WATTCP.CFG parser for "WINPKT." keywords in WATTCP.CFG.
Definition: winpkt.c:233
Contains some information about a network adapter.
Definition: packet32.h:184
int W32_CALL pkt_get_addr(mac_address *eth)
Return the MAC address.
Definition: winpkt.c:633
Core definitions.
const char * list_lookup(DWORD type, const struct search_list *list, int num)
Search 'list' for 'type' and return it's name.
Definition: misc.c:929
static enum eth_init_result open_swsvpkt_adapter(const char *name)
Open the named SwsVpkt device.
Definition: winpkt.c:1603
char * _strlcpy(char *dst, const char *src, size_t len)
Similar to strncpy(), but always returns 'dst' with 0-termination.
Definition: strings.c:226
const char * MAC_address(const void *addr)
Return hexa-decimal string for an 6/7 byte MAC-address.
Definition: misc.c:963
int W32_CALL pkt_send(const void *tx, int length)
Send a link-layer frame.
Definition: winpkt.c:937
const char * expand_var_str(const char *str)
Return a string with a environment variable expanded (only one).
Definition: pcconfig.c:231
FILE * fopen_excl(const char *file, const char *mode)
WIN32: Open an existing file (or create) in share-mode but deny other processes to write to the file...
Definition: misc.c:439
convert to 8-bit byte
Definition: tcp.h:425
static void swsvpkt_callback(struct SwsVpktUsr *, const void *, unsigned)
Our low-level SwsVpkt receive callback.
Definition: winpkt.c:846
const char *W32_CALL pkt_strerror(int code)
Return textual error representing error-code.
Definition: winpkt.c:1145
int W32_CALL pkt_release(void)
Definition: winpkt.c:577
static BOOL get_if_type_airpcap(const AIR_ADAPTER *adapter, WORD *type)
Definition: winpkt.c:1249
Structure containing an OID request.
Definition: packet32.h:218
Describes an opened network adapter.
Definition: packet32.h:194
int W32_CALL pkt_get_mtu(void)
Return PKTDRVR maximum-transmit-units (MTU).
Definition: winpkt.c:1136
int W32_CALL pkt_get_rcv_mode(void)
Gets the receive mode of the interface (can never be mode 0).
Definition: winpkt.c:1017
void W32_CALL pkt_free_pkt(const void *pkt)
Release a packet from the receive queue.
Definition: winpkt.c:700
DWORD W32_CALL pkt_dropped(void)
Return number of packets dropped.
Definition: winpkt.c:1129
char * strrtrim(char *s)
Trim trailing blanks (space/tab) from a string.
Definition: strings.c:255
int _pkt_rxmode0
startup receive mode
Definition: winpkt.c:90
WORD _pkt_ip_ofs
Offset from MAC-header to IP-header.
Definition: winpkt.c:86
Definition: zinftree.h:24
BOOL _eth_SwsVpkt
for DOS and Win32 programs
Definition: pcsed.c:58
int W32_CALL pkt_buf_wipe(void)
Clear the receive queue.
Definition: winpkt.c:686
static enum eth_init_result open_winpcap_adapter(const char *name)
Open the WinPcap named device.
Definition: winpkt.c:1517
static enum eth_init_result open_wanpacket_adapter(const char *name)
Open the named WanPacket device.
Definition: winpkt.c:1576
int _pkt_rxmode
active receive mode
Definition: winpkt.c:89
BROADCAST + all multicast.
Definition: pcpkt.h:113
Definition: tcp.h:778
receive all packets on network
Definition: pcpkt.h:114
BOOL _watt_fatal_error
Definition: misc.c:60
int W32_CALL pkt_set_rcv_mode(int mode)
Sets the receive mode of the interface.
Definition: winpkt.c:984
WORD _pktdevclass
Driver class; <tcp.h> for values.
Definition: winpkt.c:85
struct pkt_info * _pkt_inf
module data that will be locked
Definition: winpkt.c:95
Berkeley Packet Filter header.
Definition: packet32.h:232
int W32_CALL pkt_get_api_ver(WORD *ver_p)
Return version of spec.
Definition: winpkt.c:1422
static DWORD __stdcall winpcap_recv_thread(void *arg)
Our low-level WinPcap capture thread.
Definition: winpkt.c:754
BOOL _eth_airpcap
for Win32 using the AirPcap adapter
Definition: pcsed.c:59
static void set_txmode(const char *value)
Select async (overlapping) tx-mode.
Definition: winpkt.c:727
int W32_CALL pkt_eth_init(mac_address *mac_addr)
Initialise WinPcap/SwsVpkt/AirPcap/WanPacket and return our MAC address.
Definition: winpkt.c:385
receive only to this interface
Definition: pcpkt.h:110
Placeholder for vital data accessed by capture thread.
Definition: pcpkt.h:206
turn off receiver
Definition: pcpkt.h:109
int _pkt_errno
Last PKTDRVR error code.
Definition: winpkt.c:88
BOOL _pktserial
Driver is a serial (SLIP/PPP) driver.
Definition: winpkt.c:87
BROADCAST + limited multicast.
Definition: pcpkt.h:112
int W32_CALL pkt_waiting(void)
Return number of packets waiting in queue.
Definition: winpkt.c:693