Watt-32 tcp/ip  2.2 dev-rel.10
pcdbug.c
Go to the documentation of this file.
1 
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <stdarg.h>
14 #include <string.h>
15 #include <setjmp.h>
16 #include <limits.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <io.h>
20 #include <arpa/nameser.h>
21 #include <resolv.h>
22 
23 #if defined(__DJGPP__) && (DJGPP_MINOR >= 4)
24 #include <sys/xdevices.h>
25 #endif
26 
27 #if (defined(WIN32) || defined(_WIN32)) && !defined(__CYGWIN__)
28 #include <fcntl.h>
29 #include <share.h>
30 #endif
31 
32 #include "wattcp.h"
33 #include "strings.h"
34 #include "pcdns.h"
35 #include "misc.h"
36 #include "run.h"
37 #include "timer.h"
38 #include "sock_ini.h"
39 #include "chksum.h"
40 #include "ip4_in.h"
41 #include "ip6_in.h"
42 #include "ip6_out.h"
43 #include "pctcp.h"
44 #include "pcsed.h"
45 #include "pcarp.h"
46 #include "pcqueue.h"
47 #include "pcpkt.h"
48 #include "pcstat.h"
49 #include "pcicmp.h"
50 #include "pcicmp6.h"
51 #include "pcconfig.h"
52 #include "netaddr.h"
53 #include "language.h"
54 #include "printk.h"
55 #include "gettod.h"
56 #include "get_xby.h"
57 #include "pppoe.h"
58 #include "ppp.h"
59 #include "split.h"
60 #include "bsddbug.h"
61 #include "pcdbug.h"
62 
63 #if defined(USE_GZIP)
64 #include "zlib.h"
65 #endif
66 
67 #if defined(USE_SCTP)
68 #include "sctp.h"
69 #endif
70 
71 #define DEBUG_RTP 1
73 const char *tcpStateName (UINT state)
74 {
75  static char buf[20];
76  static const char *tcpStates[] = {
77  "LISTEN", "RESOLVE", "SYNSENT", "SYNREC", "ESTAB",
78  "ESTCLOSE", "FINWT1", "FINWT2", "CLOSWT", "CLOSING",
79  "LASTACK", "TIMEWT", "CLOSED"
80  };
81 
82  if (state < DIM(tcpStates))
83  return tcpStates [(int)state];
84  return itoa (state, buf, 10);
85 }
86 
87 DebugProc debug_xmit = NULL;
88 DebugProc debug_recv = NULL;
89 
90 #if !defined(USE_DEBUG)
91 
92 void dbug_init (void)
93 {
94  outsnl ("Debug-mode disabled");
95 }
96 
97 #else /* rest of file */
98 
99 static void dbug_exit (void);
100 static void dbug_close (void);
101 static void dump_ip_opt (const void *opt, int len);
102 static void dump_tcp_opt(const void *opt, int len, DWORD ack);
103 static DWORD dump_data (const void *data, UINT datalen);
104 static int udp_dump (const _udp_Socket *sock, const in_Header *ip);
105 static int tcp_dump (const _tcp_Socket *sock, const in_Header *ip);
106 
107 static unsigned dns_dump (const BYTE *, unsigned, unsigned);
108 static const BYTE *dns_resource (const BYTE *, const BYTE *, const BYTE *);
109 static const BYTE *dns_labels (const BYTE *, const BYTE *, const BYTE *);
110 
111 static int write_pcap_header (void);
112 static int write_pcap_packet (const void *pkt, BOOL out);
113 
114 #if defined(USE_PPPOE)
115  static unsigned ccp_dump (const BYTE *bp);
116  static unsigned lcp_dump (const BYTE *bp);
117  static unsigned ipcp_dump (const BYTE *bp);
118 #endif
119 
120 #if (DOSX) && !defined(__MINGW64__)
121  #define PRINT_CPU_INFO
122  #include "cpumodel.h"
123  static void print_cpu_info (void);
124 #endif
125 
126 
127 static void (W32_CALL *prev_hook) (const char*, const char*) = NULL;
128 
129 static jmp_buf dbg_jmp;
130 static char dbg_name [MAX_PATHLEN+1] = "WATTCP.DBG";
131 static BOOL dbg_linebuf = FALSE;
132 static BOOL pcap_mode = FALSE;
133 static DWORD now; /* ticks or milli-sec */
134 static BOOL outbound; /* transmitting packet? */
135 static BOOL in_dbug_dump;
136 static BOOL use_gzip; /* if using pcap-mode, use gzip-compression */
137 static BOOL use_ods = FALSE; /* Win32: use OutputDebugString() */
138 static char ip4_src [20];
139 static char ip4_dst [20];
140 
141 static union {
142  FILE *stream;
143  void *gz_stream;
144  } dbg_file;
145 
146 
147 /* IP-fragment handling
148  */
149 #define IS_FRAG 0x01 /* is this a fragment? */
150 #define IS_LAST 0x02 /* is this last fragment? */
151 #define IS_FIRST 0x04 /* is this first fragment? */
152 
153 static int frag_status; /* IPv4 fragment bits */
154 
155 
156 #if defined(USE_IPV6)
157  static char ip6_src [50];
158  static char ip6_dst [50];
159  static int udp6_dump (const _udp_Socket *sock, const in6_Header *ip);
160 #endif
161 
162 static struct {
163  char MAC;
164  char ARP;
165  char RARP;
166  char IP; /* both IPv4 and IPv6 */
167  char BCAST;
168  char MCAST;
169  char LOOP;
170  char NONE;
171  } filter = { 1,1,1,1,1,1,0,0 };
172 
173 static struct {
174  char MAC;
175  char LLC;
176  char ARP;
177  char RARP;
178  char IP;
179  char UDP;
180  char TCP;
181  char ICMP;
182  char IGMP;
183  char SCTP;
184  } debug = { 0,0,1,1,1,1,1,1,1,1 };
185 
190 BOOL dbg_mode_all = 1;
191 BOOL dbg_print_stat = 1;
192 BOOL dbg_dns_details = 1;
193 
194 #if defined(USE_GZIP)
195 static DWORD bytes_raw = 0UL; /* raw uncompressed bytes written */
196 #endif
197 
198 
199 /*----------------------------------------------------------------------*/
200 
201 BOOL dbug_file (void)
202 {
203  if (pcap_mode) /* don't let anyone mess with this file */
204  return (FALSE);
205  return (dbg_file.stream != NULL || use_ods);
206 }
207 
208 void dbug_open (void)
209 {
210  const char *fmode = pcap_mode ? "w+b" : "w+t";
211  const char *end;
212 
213  if (dbg_file.stream || use_ods) /* Already opened; quit */
214  return;
215 
216 #if defined(__DJGPP__) && (DJGPP_MINOR >= 4) /* Just for testing */
217  if (!stricmp(dbg_name,"/dev/zero"))
218  __install_dev_zero();
219 
220  else if (!stricmp(dbg_name,"/dev/full"))
221  __install_dev_full();
222 #endif
223 
224  end = strchr (dbg_name, '\0');
225  use_gzip = (end && !stricmp(end-3,".gz"));
226 
227  if (!stricmp(dbg_name,"con") || !stricmp(dbg_name,"stdout"))
228  dbg_file.stream = stdout;
229 
230  else if (!stricmp(dbg_name,"stderr"))
231  dbg_file.stream = stderr;
232 
233 #if defined(WIN32)
234  else if (!stricmp(dbg_name,"$ods"))
235  {
236  use_ods = TRUE;
237  goto quit;
238  }
239 #endif
240 
241 #if defined(USE_GZIP)
242  else if (pcap_mode && use_gzip)
243  {
244 #if defined(WIN32) && !defined(__WATCOMC__) && !defined(__CYGWIN__)
245  int fd = _sopen (dbg_name, _O_CREAT | _O_TRUNC | _O_WRONLY,
246  SH_DENYWR, S_IREAD | S_IWRITE);
247  if (fd > -1)
248  dbg_file.gz_stream = gzdopen (fd, "w+b2"); /* compression level 2 */
249 #else
250  errno = 0;
251  dbg_file.gz_stream = gzopen (dbg_name, "w+b2"); /* compression level 2 */
252 #endif
253  }
254 #endif /* USE_GZIP */
255  else
256  {
257  dbg_file.stream = fopen_excl (dbg_name, fmode);
258  use_gzip = FALSE;
259  }
260 
261  if (!dbg_file.stream)
262  {
263  (*_printf) (_LANG("ERROR: unable to open debug file %s; %s\n"),
264  dbg_name, strerror(errno));
265  errno = 0; /* clear it. It coult confuse callers */
266  return;
267  }
268 
269  if (pcap_mode)
270  {
271  if (dbg_file.stream == stdout || dbg_file.stream == stderr)
272  {
273  outsnl (_LANG("ERROR: cannot debug to screen with \"DEBUG.PCAP=1\""));
274  dbug_close();
275  return;
276  }
277  if (write_pcap_header() < 0)
278  {
279  (*_printf) (_LANG("ERROR: Failed to write pcap header; %s\n"),
280  strerror(errno));
281  dbug_close();
282  return;
283  }
284  }
285 #if !defined(__BORLANDC__) /* buggy output with this */
286  else if (dbg_linebuf)
287  {
288  static char buf[256];
289  setvbuf (dbg_file.stream, buf, _IOLBF, sizeof(buf));
290  }
291 #endif
292 
293 #if defined(WIN32)
294  quit:
295 #endif
296 
297  RUNDOWN_ADD (dbug_exit, 5);
298 }
299 
300 /*
301  * Return TRUE if MAC address is multicast (LSB bit 0 set).
302  */
303 static __inline BOOL MAC_is_mcast (const void *addr)
304 {
305  return ((*(const BYTE*)addr & 1) == 1);
306 }
307 
308 /*
309  * Return TRUE if MAC address is broadcast.
310  */
311 static __inline BOOL MAC_is_bcast (const void *addr)
312 {
313  return (!memcmp(addr, _eth_brdcast, _eth_mac_len));
314 }
315 
316 /*
317  * Using NDIS3PKT causes all non-broadcast packets sent to
318  * appear in receive buffer approx 100 msec later.
319  * WinPcap: Also if _pkt_rxmode == RXMODE_ALL_LOCAL.
320  *
321  * To avoid confusion, we print a warning in this case.
322  */
323 static __inline BOOL is_looped (const in_Header *ip)
324 {
325  if (outbound || _pktserial)
326  return (FALSE);
327 
328  if (memcmp(MAC_SRC(ip), _eth_addr, _eth_mac_len))
329  return (FALSE);
330 
331  if (MAC_TYP(ip) != IP4_TYPE) /* assume looped if not IPv4 */
332  return (TRUE);
333 
334  /* if MAC-src matches, but IP-src is different it could be
335  * Winsock sending. Thus it's not a looped packet.
336  */
337  return (ntohl(ip->source) == my_ip_addr);
338 }
339 
340 /*
341  * Return TRUE if MAC destination address of received/sent link-layer
342  * packet:
343  * - matches our link-layer address.
344  * - is broadcast and we don't filter broadcast.
345  * - is multicast and we don't filter multicast.
346  */
347 static __inline BOOL match_link_destination (const void *addr)
348 {
349  if (!memcmp(addr, _eth_addr, _eth_mac_len) ||
350  (!filter.BCAST && MAC_is_bcast(addr)) ||
351  (!filter.MCAST && MAC_is_mcast(addr)))
352  return (TRUE);
353  return (FALSE);
354 }
355 
356 /*
357  * Return TRUE if destination address of received/sent ARP packet:
358  * - matches our ether/IP-address.
359  * - is broadcast and we don't filter broadcast
360  * (ARP/RARP packets should never use multicast in it's header).
361  */
362 static __inline BOOL match_arp_rarp (const arp_Header *arp)
363 {
364  if (!memcmp(&arp->dstEthAddr, _eth_addr, _eth_mac_len) ||
365  _ip4_is_local_addr(intel(arp->dstIPAddr)))
366  return (TRUE);
367 
368  if (!filter.BCAST && MAC_is_bcast(&arp->dstEthAddr))
369  return (TRUE);
370  return (FALSE);
371 }
372 
373 /*
374  * Return TRUE if destination address of received/sent IP packet:
375  * - matches our IP-address.
376  * - is broadcast and we don't filter (directed) IP-broadcast.
377  */
378 static __inline BOOL match_ip4_dest (const in_Header *ip)
379 {
380  DWORD destin = intel (ip->destination);
381 
382  if (_ip4_is_local_addr(destin) || (!filter.BCAST && _ip4_is_ip_brdcast(ip)))
383  return (TRUE);
384  return (FALSE);
385 }
386 
387 #if defined(USE_IPV6)
388 static __inline BOOL match_ip6_dest (const in6_Header *ip)
389 {
390  const void *dest = &ip->destination;
391 
392  if (_ip6_is_local_addr(dest) ||
393  IN6_IS_ADDR_MC_GLOBAL(dest))
394  return (TRUE);
395  return (FALSE);
396 }
397 #endif
398 
399 /*
400  * Return checksum and print "ok" or "ERROR"
401  */
402 static __inline const char *do_check_sum (WORD value, const void *p, int len)
403 {
404  static char buf[20];
405  WORD chk = CHECKSUM (p, len);
406 
407  sprintf (buf, "%04X (%s)", value, (chk == 0xFFFF) ? "ok" : "ERROR");
408  return (buf);
409 }
410 
411 /*
412  * Return name of some known link-layer protocols.
413  */
414 static __inline const char *link_protocol (WORD type)
415 {
416  switch (type)
417  {
418  case IP4_TYPE:
419  return ("IP");
420  case IP6_TYPE:
421  return ("IP6");
422  case ARP_TYPE:
423  return ("ARP");
424  case RARP_TYPE:
425  return ("RARP");
426  case IEEE802_1Q_TYPE:
427  return ("VLAN");
428  case PPPOE_DISC_TYPE:
429  return ("PPPoE DISCOVERY");
430  case PPPOE_SESS_TYPE:
431  return ("PPPoE SESSION");
432  default:
433  return ("unknown");
434  }
435 }
436 
437 /*
438  * Return name of known IP-protocols.
439  */
440 static __inline const char *ip4_protocol (BYTE prot)
441 {
442  static char buf[4];
443 
444  switch (prot)
445  {
446  case UDP_PROTO:
447  return ("UDP");
448  case TCP_PROTO:
449  return ("TCP");
450  case ICMP_PROTO:
451  return ("ICMP");
452  case IGMP_PROTO:
453  return ("IGMP");
454  case SCTP_PROTO:
455  return ("SCTP");
456  }
457  return itoa (prot, buf, 10);
458 }
459 
460 /*
461  * Return name for IP's "Type Of Service".
462  */
463 static const char *type_of_service (BYTE tos)
464 {
465  static char buf[30];
466  char *p = buf;
467 
468  if (tos == 0)
469  return (" 0");
470 
471  *p = '\0';
472  if (tos & IP_MINCOST)
473  {
474  strcat (buf, " Mcost");
475  tos &= ~IP_MINCOST;
476  }
477  if (tos & IP_RELIABILITY)
478  {
479  strcat (buf, " Rel");
480  tos &= ~IP_RELIABILITY;
481  }
482  if (tos & IP_THROUGHPUT)
483  {
484  strcat (buf, " ThPut");
485  tos &= ~IP_THROUGHPUT;
486  }
487  if (tos & IP_LOWDELAY)
488  {
489  strcat (buf, " LwDly");
490  tos &= ~IP_LOWDELAY;
491  }
492  p = strchr (buf, '\0');
493  if (tos)
494  sprintf (p, " %02X", tos);
495  return (buf);
496 }
497 
498 /*
499  * Format time for "Round Trip Time" in msec.
500  */
501 static __inline const char *RTT_str (DWORD rtt, DWORD now)
502 {
503  static char buf[40];
504 
505  if (rtt == 0UL || rtt < now)
506  return ("--"); /* RTT timer stopped */
507 
508  sprintf (buf, "%ld", get_timediff (rtt, now));
509  return (buf);
510 }
511 
512 
513 /*
514  * Return string for ARP/RARP opcodes.
515  */
516 static __inline const char *arp_opcode (WORD code)
517 {
518  if (code == ARP_REQUEST || code == RARP_REQUEST)
519  return ("Request");
520 
521  if (code == ARP_REPLY || code == RARP_REPLY)
522  return ("Reply");
523 
524  return ("? op");
525 }
526 
527 /*
528  * Print IP source/destination addresses and ports;
529  * "host1 (a) -> host2 (b)"
530  *
531  * Note: the udp_Header src/dst port field are not printed.
532  */
533 static void dump_addr_port (const char *proto,
534  const void *sock,
535  const in_Header *ip)
536 {
537  const tcp_Header *tcp = (const tcp_Header*) ((BYTE*)ip + in_GetHdrLen(ip));
538 
539  if (!sock)
540  dbug_printf ("%s: NO SOCKET: %s (%d) -> %s (%d)\n", proto,
541  ip4_src, intel16(tcp->srcPort),
542  ip4_dst, intel16(tcp->dstPort));
543  else
544  {
545  const _tcp_Socket *sk = (const _tcp_Socket*) sock;
546 
547  if (outbound)
548  dbug_printf ("%s: %s (%d) -> %s (%d), sock %" ADDR_FMT "\n", proto,
549  _inet_ntoa(NULL,my_ip_addr), sk->myport,
550  _inet_ntoa(NULL,sk->hisaddr), sk->hisport,
551  ADDR_CAST(sock));
552 
553  else dbug_printf ("%s: %s (%d) -> %s (%d), sock %" ADDR_FMT "\n", proto,
554  _inet_ntoa(NULL,sk->hisaddr), sk->hisport,
555  _inet_ntoa(NULL,my_ip_addr), sk->myport,
556  ADDR_CAST(sock));
557  }
558 }
559 
560 #if defined(USE_IPV6)
561 static __inline void ip6_addr_type (char *ret, const void *addr)
562 {
563  if (IN6_IS_ADDR_UNSPECIFIED(addr))
564  strcpy (ret, "(anycast) ");
565 
566  else if (IN6_IS_ADDR_MULTICAST(addr))
567  strcpy (ret, "(multicast) ");
568 
569  else if (IN6_IS_ADDR_MC_NODELOCAL(addr))
570  strcpy (ret, "(MC node) ");
571 
572  else if (IN6_IS_ADDR_MC_LINKLOCAL(addr))
573  strcpy (ret, "(MC link) ");
574 
575  else if (IN6_IS_ADDR_MC_SITELOCAL(addr))
576  strcpy (ret, "(MC site) ");
577 
578  else if (IN6_IS_ADDR_MC_GLOBAL(addr))
579  strcpy (ret, "(MC global) ");
580 
581  else if (IN6_IS_ADDR_V4MAPPED(addr))
582  strcpy (ret, "(ip4-mapped) ");
583 
584  else if (IN6_IS_ADDR_V4COMPAT(addr))
585  strcpy (ret, "(ip4-compat) ");
586 
587  else if (IN6_IS_ADDR_LOOPBACK(addr))
588  strcpy (ret, "(loopback) ");
589 
590  else *ret = '\0';
591 }
592 
593 static void dump_addr6_port (const char *proto,
594  const void *sock,
595  const in6_Header *ip)
596 {
597  const tcp_Header *tcp = (const tcp_Header*) (ip + 1);
598  const _tcp_Socket *sk = (const _tcp_Socket*) sock;
599 
600  if (!sock)
601  dbug_printf ("%s: NO SOCKET: %s (%d) -> %s (%d)\n", proto,
602  ip6_src, intel16(tcp->srcPort),
603  ip6_dst, intel16(tcp->dstPort));
604 
605  else if (outbound)
606  dbug_printf ("%s: %s (%d) -> %s (%d)\n", proto,
607  _inet6_ntoa(&in6addr_my_ip),sk->myport,
608  _inet6_ntoa(sk->his6addr), sk->hisport);
609 
610  else dbug_printf ("%s: %s (%d) -> %s (%d)\n", proto,
611  _inet6_ntoa(sk->his6addr), sk->hisport,
612  _inet6_ntoa(&in6addr_my_ip),sk->myport);
613 }
614 #endif
615 
616 
617 /*----------------------------------------------------------------------*/
618 
619 static void link_head_dump (const union link_Packet *pkt)
620 {
621  const struct eth_Header *eth;
622  const char *src_name, *dst_name;
623  WORD type;
624 
625  if (_pktdevclass == PDCLASS_TOKEN || _pktdevclass == PDCLASS_TOKEN_RIF)
626  {
627  const struct tok_Header *tok = &pkt->tok.head;
628 
629  dbug_printf ("TR: destin %s, AC %02X, FC %02X\n"
630  " source %s, DSAP %02X, SSAP %02X, Ctrl %02X\n"
631  " type %s (%04X)\n",
632  MAC_address (tok->destination), tok->accessCtrl, tok->frameCtrl,
633  MAC_address (tok->source), tok->DSAP, tok->SSAP, tok->ctrl,
634  link_protocol(tok->type), intel16(tok->type));
635  return;
636  }
637 
638  if (_pktdevclass == PDCLASS_FDDI)
639  {
640  const struct fddi_Header *fddi = &pkt->fddi.head;
641 
642  dbug_printf ("FDDI: destin %s, FC %02X\n"
643  " source %s, DSAP %02X, SSAP %02X, Ctrl %02X\n"
644  " type %s (%04X)\n",
645  MAC_address (fddi->destination), fddi->frameCtrl,
646  MAC_address (fddi->source), fddi->DSAP, fddi->SSAP,
647  fddi->ctrl, link_protocol(fddi->type), intel16(fddi->type));
648  return;
649  }
650 
651  if (_pktdevclass == PDCLASS_ARCNET)
652  {
653  static const struct search_list arcnet_protos[] = {
654  { ARCNET_DP_BOOT, "DataPoint Boot" },
655  { ARCNET_DP_MOUNT, "DataPoint Mount" },
656  { ARCNET_PL_BEACON, "PowerLAN Beacon" },
657  { ARCNET_PL_BEACON2, "PowerLAN Beacon2" },
658  { ARCNET_DIAG, "Diagnose" },
659  { ARCNET_IP6, "IPv6" },
660  { ARCNET_BACNET, "BACNET" },
661  { ARCNET_IP_1201, "IPv4 (RFC-1201)" },
662  { ARCNET_ARP_1201, "ARP (RFC-1201)" },
663  { ARCNET_RARP_1201, "RARP (RFC-1201)" },
664  { ARCNET_ATALK, "AppleTalk" },
665  { ARCNET_ETHER, "Raw Ether" }, /* MS LAN-Man/WfWg */
666  { ARCNET_NOVELL, "Novell Encap" },
667  { ARCNET_IP_1051, "IPv4 (RFC-1051)" },
668  { ARCNET_ARP_1051, "ARP (RFC-1051)" },
669  { ARCNET_BANYAN, "Banyan" },
670  { ARCNET_IPX, "IPX" },
671  { ARCNET_LANSOFT, "LanSoft" }
672  };
673  const struct arcnet_Header *arc = &pkt->arc.head;
674  const char *proto = list_lookup (arc->type, arcnet_protos,
675  DIM(arcnet_protos));
676 
677  dbug_printf ("ARCNET:destin %02X, flags %02X, sequence %04X\n"
678  " source %02X %s\n"
679  " type %s\n",
680  arc->destination, arc->flags, arc->sequence,
681  arc->source, arc->flags == 0xFF ? "Exc-packet" : "",
682  proto);
683  return;
684  }
685 
686  WATT_ASSERT (_pktdevclass == PDCLASS_ETHER);
687 
688  eth = &pkt->eth.head;
689 
690  /* src/dst_names comes from /etc/ethers file
691  */
692  src_name = GetEtherName (&eth->source);
693  dst_name = GetEtherName (&eth->destination);
694 
695  dbug_printf ("ETH: destin %s %s %s\n"
696  " source %s %s %s\n",
697  MAC_address (&eth->destination),
698  MAC_is_bcast(&eth->destination) ? "(broadcast)" :
699  MAC_is_mcast(&eth->destination) ? "(multicast)" : "",
700  dst_name ? dst_name : "",
701  MAC_address (&eth->source),
702  MAC_is_bcast(&eth->source) ? "(broadcast)" :
703  MAC_is_mcast(&eth->source) ? "(multicast)" : "",
704  src_name ? src_name : "");
705 
706  type = intel16 (eth->type);
707  if (type == 0xFFFF)
708  {
709  dbug_printf (" Novell IPX\n");
710  }
711  else if (type < 0x600) /* type is LLC length field */
712  {
713  const llc_Header *llc = (const llc_Header*) (eth+1);
714  unsigned len = type;
715 
716  dbug_printf (" IEEE 802.3 encap (LLC: DSAP %02X, SSAP %02X, len %u)\n",
717  llc->DSAP, llc->SSAP, len);
718  }
719  else
720  dbug_printf (" type %s (%04X)\n", link_protocol(eth->type), type);
721 }
722 
723 /*----------------------------------------------------------------------*/
724 
725 static int arp_dump (const arp_Header *arp)
726 {
727  _inet_ntoa (ip4_src, intel(arp->srcIPAddr));
728  _inet_ntoa (ip4_dst, intel(arp->dstIPAddr));
729 
730  return dbug_printf ("ARP: %s (%d), hw %04X, type %04X\n"
731  " %s (%s) -> %s (%s)\n",
732  arp_opcode(arp->opcode), intel16(arp->opcode),
733  arp->hwType, intel16(arp->protType),
734  MAC_address (&arp->srcEthAddr), ip4_src,
735  MAC_address (&arp->dstEthAddr), ip4_dst);
736 }
737 
738 /*----------------------------------------------------------------------*/
739 
740 static int rarp_dump (const rarp_Header *rarp)
741 {
742  _inet_ntoa (ip4_src, intel(rarp->srcIPAddr));
743  _inet_ntoa (ip4_dst, intel(rarp->dstIPAddr));
744 
745  return dbug_printf ("RARP: %s (%d), hw %04X, type %04X\n"
746  " %s (%s) -> %s (%s)\n",
747  arp_opcode(rarp->opcode), intel16(rarp->opcode),
748  rarp->hwType, intel16(rarp->protType),
749  MAC_address (&rarp->srcEthAddr), ip4_src,
750  MAC_address (&rarp->dstEthAddr), ip4_dst);
751 }
752 
753 /*----------------------------------------------------------------------*/
754 
755 static void ip4_dump (const in_Header *ip)
756 {
757  WORD ihl, flg;
758  DWORD ofs;
759  int opt_len;
760 
761  ofs = intel16 (ip->frag_ofs);
762  flg = (WORD) (ofs & ~IP_OFFMASK);
763  ofs = (ofs & IP_OFFMASK) << 3;
764 
765  frag_status = 0;
766 
767  if (flg & IP_MF)
768  {
769  frag_status |= IS_FRAG;
770 
771  /* This is 1st fragment. */
772  if (ofs == 0)
773  frag_status |= IS_FIRST;
774  }
775  else if (ofs)
776  frag_status = (IS_FRAG | IS_LAST); /* last fragment */
777 
778  if (!debug.IP)
779  return;
780 
781  dbug_printf ("IP4: %s -> %s\n", ip4_src, ip4_dst);
782 
783  ihl = in_GetHdrLen (ip);
784  if (ihl < sizeof(*ip))
785  {
786  dbug_write (" Bad header\n");
787  return;
788  }
789 
790  dbug_printf (" IHL %u, ver %u, tos%s, len %u,"
791  " ttl %u, prot %s, chksum %s\n"
792  " id %04X, ofs %lu",
793  ihl, (BYTE)ip->ver, type_of_service(ip->tos), intel16(ip->length),
794  (BYTE)ip->ttl, ip4_protocol (ip->proto),
795  do_check_sum (ip->checksum, ip, ihl),
796  intel16 (ip->identification), ofs);
797 
798  if (flg & IP_CE)
799  dbug_write (", CE");
800 
801  if (flg & IP_DF)
802  dbug_write (", DF");
803 
804  if (frag_status)
805  {
806  if (frag_status & IS_FIRST)
807  dbug_write (", 1st frag");
808  if (frag_status & IS_LAST)
809  dbug_write (", last frag");
810  }
811 
812  dbug_putc ('\n');
813  opt_len = ihl - sizeof(*ip);
814  if (opt_len > 0)
815  dump_ip_opt (ip+1, opt_len);
816 }
817 
818 /*----------------------------------------------------------------------*/
819 
820 static int ip4_orig_dump (const in_Header *this_ip,
821  const in_Header *orig_ip, int icmp_len)
822 {
823  WORD ihl;
824  DWORD ofs;
825 
826  if (icmp_len < SIZEOF(*orig_ip))
827  {
828  dbug_write (" Too little of original IP-header\n");
829  return dump_data (this_ip, intel16(this_ip->length));
830  }
831 
832  ihl = in_GetHdrLen (orig_ip);
833  if (ihl < sizeof(*orig_ip))
834  {
835  dbug_write (" Bad orig. header\n");
836  return dump_data (this_ip, intel16(this_ip->length));
837  }
838 
839  dbug_printf (" Orig IP: %s -> %s\n",
840  _inet_ntoa(NULL,intel(orig_ip->source)),
841  _inet_ntoa(NULL,intel(orig_ip->destination)));
842 
843  ofs = (intel16(orig_ip->frag_ofs) & IP_OFFMASK) << 3;
844 
845  dbug_printf (" IHL %u, ver %u, tos%s, len %u,"
846  " ttl %u, prot %s\n"
847  " chksum %s, id %04X, ofs %lu\n",
848  ihl, (BYTE)orig_ip->ver, type_of_service(orig_ip->tos),
849  intel16(orig_ip->length), (BYTE)orig_ip->ttl,
850  ip4_protocol (orig_ip->proto),
851  do_check_sum (orig_ip->checksum, orig_ip, ihl),
852  intel16 (orig_ip->identification), ofs);
853 
854  if (icmp_len <= ihl)
855  dbug_write (" No transport header present\n");
856 
857  else if (orig_ip->proto == TCP_PROTO && icmp_len - ihl >= 4)
858  {
859  const tcp_Header *tcp = (const tcp_Header*) ((const BYTE*)orig_ip + ihl);
860  dbug_printf (" TCP: port %u -> %u\n",
861  intel16(tcp->srcPort), intel16(tcp->dstPort));
862  }
863  else if (orig_ip->proto == UDP_PROTO && icmp_len - ihl >= 4)
864  {
865  const udp_Header *udp = (const udp_Header*) ((const BYTE*)orig_ip + ihl);
866  dbug_printf (" UDP: port %u -> %u\n",
867  intel16(udp->srcPort), intel16(udp->dstPort));
868  }
869 
870  if (icmp_len > 0) /* consider only original IP as payload */
871  return dump_data (orig_ip, icmp_len);
872  return (1);
873 }
874 
875 /*----------------------------------------------------------------------*/
876 
877 static int icmp4_dump (const in_Header *ip)
878 {
879  WORD len = in_GetHdrLen (ip);
880  const ICMP_PKT *icmp = (const ICMP_PKT*) ((const BYTE*)ip + len);
881  const char *type_str, *chk_ok;
882  char buf[200] = "";
883  char *p = buf;
884  int type, code;
885 
886  len = intel16 (ip->length) - len; /* ICMP length */
887  type = icmp->unused.type;
888  code = icmp->unused.code;
889 
890  if (len < sizeof(struct ICMP_info))
891  {
892  dbug_write ("ICMP: Short header\n");
893  return (1);
894  }
895 
896  /* Simply dump the remaining data if this is a fragment.
897  */
898  if (frag_status)
899  return dump_data (icmp, len);
900 
901  switch (type)
902  {
903  case ICMP_UNREACH:
904  type_str = icmp_type_str [ICMP_UNREACH];
905  if (code < DIM(icmp_unreach_str))
906  sprintf (buf, "%s: %s", type_str, icmp_unreach_str[code]);
907  else sprintf (buf, "%s: code %d", type_str, code);
908  break;
909 
910  case ICMP_TIMXCEED:
911  type_str = icmp_type_str [ICMP_TIMXCEED];
912  if (code < DIM(icmp_exceed_str))
913  p += sprintf (p, "%s: %s", type_str, icmp_exceed_str[code]);
914  else p += sprintf (buf, "%s: code %d", type_str, code);
915  break;
916 
917  case ICMP_REDIRECT:
918  if (code < DIM(icmp_redirect_str))
919  strcpy (buf, icmp_redirect_str[code]);
920  else sprintf (buf, "Redirect; code %d", code);
921  break;
922 
923  case ICMP_PARAMPROB:
924  if (code)
925  sprintf (buf, "Param prob code %d", code);
926  else sprintf (buf, "Param prob at %d", icmp->pointer.pointer);
927  break;
928 
929  case ICMP_MASKREQ:
930  case ICMP_MASKREPLY:
931  sprintf (buf, "ICMP %s: %s", icmp_type_str[type],
932  _inet_ntoa(NULL, intel(icmp->mask.mask)));
933  break;
934 
935 #if 0
936 
938  case ICMP_ROUTERADVERT:
939  case ICMP_ROUTERSOLICIT:
940  case ICMP_TSTAMP:
941  case ICMP_TSTAMPREPLY:
942  case ICMP_IREQ:
943  case ICMP_IREQREPLY:
944 #endif
945 
946  default:
947  sprintf (buf, "%s (%d), code %d",
948  type < DIM(icmp_type_str) ?
949  icmp_type_str[type] : "Unknown", type, code);
950  }
951 
952  chk_ok = do_check_sum (icmp->unused.checksum, icmp, len);
953 
954  dbug_printf ("ICMP: %s -> %s\n"
955  " %s, chksum %s\n",
956  ip4_src, ip4_dst, buf, chk_ok);
957 
958  if (type == ICMP_UNREACH || type == ICMP_PARAMPROB)
959  return ip4_orig_dump (ip, &icmp->ip.ip, len - 8);
960 
961  if (type == ICMP_TIMXCEED)
962  return ip4_orig_dump (ip, &icmp->unused.ip, len - 8);
963 
964  return dump_data (icmp, len);
965 }
966 
967 /*----------------------------------------------------------------------*/
968 
969 #if defined(USE_MULTICAST)
970 
971 static int igmp0_dump (const IGMPv0_packet *igmp, WORD len)
972 {
973  ARGSUSED (len);
974  return dbug_printf ("IGMP: unfinished IGMP v0 parser. addr %s\n",
975  _inet_ntoa(NULL, intel(igmp->address)));
976 }
977 
978 static int igmp1_dump (const IGMPv1_packet *igmp, WORD len)
979 {
980  static const struct search_list types[] = {
981  { IGMPv1_QUERY, "Query" },
982  { IGMPv1_REPORT, "Report" },
983  { IGMPv1_DVMRP, "DVMRP" }
984  };
985  return dbug_printf ("IGMP: %s, ver %d, chksum %s, addr %s\n",
986  list_lookup(igmp->type, types, DIM(types)),
987  igmp->version, do_check_sum(igmp->checksum, igmp, len),
988  _inet_ntoa(NULL, intel(igmp->address)));
989 }
990 
991 static int igmp2_dump (const IGMPv2_packet *igmp, WORD len)
992 {
993  ARGSUSED (len);
994  return dbug_printf ("IGMP: unfinished IGMP v2 parser. addr %s\n",
995  _inet_ntoa(NULL, intel(igmp->address)));
996 }
997 
998 static int igmp3_dump (const IGMPv3_packet *igmp, WORD len)
999 {
1000  ARGSUSED (len);
1001  return dbug_printf ("IGMP: unfinished IGMP v3 parser. addr %s\n",
1002  _inet_ntoa(NULL, intel(igmp->address)));
1003 }
1004 
1005 static int igmp_dump (const in_Header *ip)
1006 {
1007  WORD hdr_len = in_GetHdrLen (ip); /* length of IP-header */
1008  const IGMPv0_packet *igmp0 = (const IGMPv0_packet*) ((const BYTE*)ip + hdr_len);
1009  const IGMPv1_packet *igmp1 = (const IGMPv1_packet*) igmp0;
1010  const IGMPv2_packet *igmp2 = (const IGMPv2_packet*) igmp0;
1011  const IGMPv3_packet *igmp3 = (const IGMPv3_packet*) igmp0;
1012  WORD igmp_len = intel16 (ip->length) - hdr_len;
1013  BOOL is_v[4] = { FALSE, FALSE, FALSE, FALSE };
1014 
1015  if (igmp_len == sizeof(*igmp1) && igmp1->version == 1) /* 8 byte */
1016  is_v[1] = TRUE;
1017 
1018  else if (igmp_len == sizeof(*igmp2)) /* 8 byte */
1019  is_v[2] = TRUE;
1020 
1021  else if (igmp_len == sizeof(*igmp0)) /* 16 byte */
1022  is_v[0] = TRUE;
1023 
1024  else if (igmp_len >= sizeof(*igmp3)) /* >= 14 byte, multiple of 4 (14,18,22..) */
1025  is_v[3] = TRUE;
1026 
1027  else
1028  return dbug_printf ("IGMP: Header length %u??\n", igmp_len);
1029 
1030  if (is_v[0])
1031  return igmp0_dump (igmp0, igmp_len);
1032  if (is_v[1])
1033  return igmp1_dump (igmp1, igmp_len);
1034  if (is_v[2])
1035  return igmp2_dump (igmp2, igmp_len);
1036  if (is_v[3])
1037  return igmp3_dump (igmp3, igmp_len);
1038 
1039  return dbug_printf ("IGMP: Unknown pkt, len %u\n", igmp_len);
1040 }
1041 #endif /* USE_MULTICAST */
1042 
1043 /*----------------------------------------------------------------------*/
1044 
1045 #if defined(USE_SCTP)
1046 /*
1047  * A simple SCTP dumper used for both SCTP inside IPv4 and IPv6 packets.
1048  *
1049  * Refs:
1050  * RFC 2960, 3309, 3758, 4460
1051  */
1052 static const struct search_list sctp_chunks[] = {
1053  { SCTP_DATA, "DATA" },
1054  { SCTP_INITIATION, "INIT" },
1055  { SCTP_INITIATION_ACK, "INIT-ACK" },
1056  { SCTP_SELECTIVE_ACK, "SACK" },
1057  { SCTP_HEARTBEAT_REQUEST, "HB REQ" },
1058  { SCTP_HEARTBEAT_ACK, "HB ACK" },
1059  { SCTP_ABORT_ASSOCIATION, "ABORT" },
1060  { SCTP_SHUTDOWN, "SHUTDOWN" },
1061  { SCTP_SHUTDOWN_ACK, "SHUTDOWN ACK" },
1062  { SCTP_OPERATION_ERR, "OP ERR" },
1063  { SCTP_COOKIE_ECHO, "COOKIE ECHO" },
1064  { SCTP_COOKIE_ACK, "COOKIE ACK" },
1065  { SCTP_ECN_ECHO, "ECN ECHO" },
1066  { SCTP_ECN_CWR, "ECN CWR" },
1067  { SCTP_SHUTDOWN_COMPLETE, "SHUTDOWN COMPLETE" },
1068  { SCTP_FORWARD_CUM_TSN, "FOR CUM TSN" },
1069  { SCTP_RELIABLE_CNTL, "REL CTRL" },
1070  { SCTP_RELIABLE_CNTL_ACK, "REL CTRL ACK" },
1071  { SCTP_ASCONF_ACK_CHUNK_ID, "ASCONF ACK CHUNK ID" },
1072  { SCTP_PKTDROP_CHUNK_ID, "PKTDROP CHUNK ID" },
1073  { SCTP_STREAM_RESET_CHUNK_ID, "STREAM RESET_CHUNK ID" },
1074  { SCTP_IETF_EXT, "IETF EXT" }
1075  };
1076 
1077 static const struct search_list sctp_params[] = {
1078  { SCTP_IPV4_PARAM_TYPE, "IPV4 PARAM TYPE" },
1079  { SCTP_IPV6_PARAM_TYPE, "IPV6 PARAM TYPE" },
1080  { SCTP_RESPONDER_COOKIE, "RESPONDER COOKIE" },
1081  { SCTP_UNRECOG_PARAM, "UNRECOG_PARAM" },
1082  { SCTP_COOKIE_PRESERVE, "COOKIE PRESERVE" },
1083  { SCTP_HOSTNAME_VIA_DNS, "HOSTNAME VIA_DNS" },
1084  { SCTP_RESTRICT_ADDR_TO, "RESTRICT ADDR_TO" },
1085  { SCTP_ECN_I_CAN_DO_ECN, "I CAN DO ECN" },
1086  { SCTP_OPERATION_SUCCEED, "OPERATION SUCCEED" },
1087  { SCTP_ERROR_NOT_EXECUTED, "ERROR NOT EXECUTED" },
1088  { SCTP_UNRELIABLE_STRM, "UNRELIABLE STRM" },
1089  { SCTP_ADD_IP_ADDRESS, "ADD IP ADDRESS" },
1090  { SCTP_DEL_IP_ADDRESS, "DEL IP ADDRESS" },
1091  { SCTP_STRM_FLOW_LIMIT, "STRM FLOW LIMIT" },
1092  { SCTP_PARTIAL_CSUM, "PARTIAL CSUM" },
1093  { SCTP_ERROR_CAUSE_TLV, "ERROR CAUSE TLV" },
1094  { SCTP_MIT_STACK_NAME, "MIT STACK NAME" },
1095  { SCTP_SETADDRESS_PRIMARY, "SETADDRESS PRIMARY" },
1096  { SCTP_RANDOM_PARAM, "RANDOM PARAM" },
1097  { SCTP_AUTH_CHUNK, "AUTH CHUNK" },
1098  { SCTP_REQ_HMAC_ALGO, "REQ HMAC ALGO" },
1099  { SCTP_SUPPORTED_EXT, "SUPPORTED EXT" }
1100  };
1101 
1102 static void sctp_dump_params (const BYTE *p, int len)
1103 {
1104  while (len > 0)
1105  {
1106  const struct sctp_ParamDesc *param = (const struct sctp_ParamDesc*) p;
1107  WORD plen = intel16 (param->paramLength);
1108  WORD ptype = intel16 (param->paramType);
1109  WORD align = 0;
1110 
1111  dbug_printf (" param: plen %d, %s\n",
1112  plen, list_lookupX(ptype, sctp_params, DIM(sctp_params)));
1113  align = plen % 4;
1114  if (align != 0)
1115  align = 4 - align;
1116  len -= plen + align;
1117  p += plen + align;
1118  }
1119 }
1120 
1121 static void sctp_dump_init (const struct sctp_Initiation *init, const BYTE *chunk_end)
1122 {
1123  dbug_printf (" init tag %lu, rwnd %lu, OS %u, MIS %u, init TSN %lu\n",
1124  intel(init->initTag), intel(init->rcvWindowCredit),
1125  intel16(init->NumPreopenStreams), intel16(init->MaxInboundStreams),
1126  intel(init->initialTSN));
1127  init++;
1128  /* optional parameters after init-message */
1129  if ((const BYTE*)init < chunk_end)
1130  sctp_dump_params ((const BYTE*)init, chunk_end - (const BYTE*)init);
1131 }
1132 
1133 static int sctp_dump (const in_Header *ip4, const in6_Header *ip6)
1134 {
1135  const struct sctp_Header *head;
1136  const struct sctp_ChunkDesc *chunk;
1137  WORD hlen, chunk_cnt, chunk_len;
1138  size_t len;
1139 
1140  if (ip4)
1141  {
1142  hlen = in_GetHdrLen (ip4);
1143  head = (const struct sctp_Header*) ((const BYTE*)ip4 + hlen);
1144  len = intel16 (ip4->length) - hlen;
1145  }
1146  else
1147  {
1148  len = intel16 (ip6->len);
1149  len = min (len, MAX_IP6_DATA-sizeof(*ip6));
1150  head = (const struct sctp_Header*) (ip6 + 1);
1151  }
1152 
1153  if (len < sizeof(*head))
1154  {
1155  dbug_printf ("SCTP: Bogus length %u\n", (unsigned)len);
1156  return (0);
1157  }
1158 
1159  dbug_printf ("SCTP: %s (%d) -> %s (%d), Verif 0x%08lX, Adler 0x%08lX\n",
1160  ip4 ? ip4_src : ip6_src, intel16(head->source),
1161  ip4 ? ip4_dst : ip6_dst, intel16(head->destination),
1162  intel(head->verificationTag), intel(head->adler32));
1163 
1164  len -= sizeof(*head);
1165  if (len < sizeof(*chunk))
1166  {
1167  dbug_printf (" no chunks!!, len %u\n", (unsigned)len);
1168  return (0);
1169  }
1170  chunk = (const struct sctp_ChunkDesc*) (head+1);
1171 
1172  for (chunk_cnt = 1; len > 0; chunk_cnt++)
1173  {
1174  const BYTE *chunk_end;
1175  WORD align;
1176 
1177  chunk_len = intel16 (chunk->chunkLength);
1178  chunk_end = ((const BYTE*)chunk + chunk_len);
1179 
1180  if (chunk_len < sizeof(*chunk))
1181  {
1182  dbug_printf ("%d) [Bad chunk length %u]\n", chunk_cnt+1, chunk_len);
1183  break;
1184  }
1185  dbug_printf (" chunk %d: [%s], len %d, flag 0x%02X\n",
1186  chunk_cnt, list_lookup(chunk->chunkID, sctp_chunks, DIM(sctp_chunks)),
1187  chunk_len, chunk->chunkFlg);
1188 
1189  if (chunk->chunkID == SCTP_INITIATION || chunk->chunkID == SCTP_INITIATION_ACK)
1190  sctp_dump_init ((const struct sctp_Initiation*)(chunk+1), chunk_end);
1191 
1192  align = chunk_len % 4;
1193  if (align != 0)
1194  align = 4 - align;
1195 
1196  chunk = (const struct sctp_ChunkDesc*) (chunk_end + align);
1197  len -= chunk_len + align;
1198  }
1199  return dump_data (chunk, len);
1200 }
1201 #endif
1202 
1203 /*----------------------------------------------------------------------*/
1204 
1205 static unsigned ip4_payload_dump (const void *sock, const in_Header *ip)
1206 {
1207 #if defined(USE_MULTICAST)
1208  if (ip->proto == IGMP_PROTO && debug.IGMP)
1209  return igmp_dump (ip);
1210 #endif
1211 
1212 #if defined(USE_SCTP)
1213  if (ip->proto == SCTP_PROTO && debug.SCTP)
1214  return sctp_dump (ip, FALSE);
1215 #endif
1216 
1217  if (ip->proto == ICMP_PROTO && debug.ICMP)
1218  return icmp4_dump (ip);
1219 
1220  if (ip->proto == UDP_PROTO && debug.UDP)
1221  return udp_dump ((const _udp_Socket*)sock, ip);
1222 
1223  if (ip->proto == TCP_PROTO && debug.TCP)
1224  return tcp_dump ((const _tcp_Socket*)sock, ip);
1225 
1226  if (debug.IP) /* dump unsupported IPv4 protocols as hex */
1227  {
1228  WORD hlen = in_GetHdrLen (ip);
1229  WORD len = intel16 (ip->length) - hlen;
1230  const BYTE *data = (const BYTE*)ip + hlen;
1231  return dump_data (data, min(len,MAX_IP4_DATA-hlen));
1232  }
1233  return (0);
1234 }
1235 
1236 /*----------------------------------------------------------------------*/
1237 
1238 #if defined(USE_IPV6)
1239 static const char *ip6_next_hdr (BYTE nxt)
1240 {
1241  switch (nxt)
1242  {
1243  case IP6_NEXT_HOP:
1244  return ("HBH");
1245  case IP6_NEXT_TCP:
1246  return ("TCP");
1247  case IP6_NEXT_UDP:
1248  return ("UDP");
1249  case IP6_NEXT_IPV6:
1250  return ("IPV6");
1251  case IP6_NEXT_ROUTING:
1252  return ("ROUTE");
1253  case IP6_NEXT_FRAGMENT:
1254  return ("FRAG");
1255  case IP6_NEXT_ESP:
1256  return ("ESP");
1257  case IP6_NEXT_AUTH:
1258  return ("AUTH");
1259  case IP6_NEXT_ICMP:
1260  return ("ICMP6");
1261  case IP6_NEXT_NONE:
1262  return ("NONE");
1263  case IP6_NEXT_DEST:
1264  return ("DEST");
1265  case IP6_NEXT_SCTP:
1266  return ("SCTP");
1267  default:
1268  return ("??");
1269  }
1270 }
1271 
1272 const char *icmp6_options (const BYTE *opt, int tot_len)
1273 {
1274  static char buf[50];
1275  char *p = buf;
1276  int len, val;
1277 
1278  while (tot_len > 0 && p < buf + DIM(buf))
1279  {
1280  switch (val = *opt++)
1281  {
1282  case ND_OPT_SOURCE_LINKADDR:
1283  p += sprintf (p, "src MAC %s, ", MAC_address(opt));
1284  break;
1285  case 0:
1286  p += sprintf (p, "EOL, ");
1287  break;
1288  default:
1289  p += sprintf (p, "opt %d?, ", val);
1290  break;
1291  }
1292  len = (*opt++) << 3;
1293  tot_len -= len;
1294  if (tot_len <= 0)
1295  {
1296  p -= 2;
1297  *p = '\0';
1298  return (buf);
1299  }
1300  }
1301  return (NULL);
1302 }
1303 
1304 static int icmp6_dump (const in6_Header *ip)
1305 {
1306  const union ICMP6_PKT *icmp = (const union ICMP6_PKT*) (ip + 1);
1307  unsigned len = intel16 (ip->len);
1308  unsigned type = icmp->unused.type;
1309  char buf[200] = "";
1310  char *p = buf;
1311  const BYTE *opt = NULL;
1312  int rc;
1313 
1314  if (len < sizeof(icmp->unused))
1315  {
1316  dbug_write ("ICMP6: Short packet\n");
1317  return (1);
1318  }
1319 
1320  switch (type)
1321  {
1322  case ICMP6_DST_UNREACH:
1323  sprintf (buf, "Dest unreach");
1324  break;
1325 
1326  case ICMP6_PACKET_TOO_BIG:
1327  sprintf (buf, "Pkt too big");
1328  break;
1329 
1330  case ICMP6_TIME_EXCEEDED:
1331  sprintf (buf, "Time exceeded");
1332  break;
1333 
1334  case ICMP6_PARAM_PROB:
1335  sprintf (buf, "Param problem");
1336  break;
1337 
1338  case ICMP6_ECHO_REQUEST:
1339  sprintf (buf, "Echo request");
1340  break;
1341 
1342  case ICMP6_ECHO_REPLY:
1343  sprintf (buf, "Echo reply");
1344  break;
1345 
1346  case ICMP6_MEMBERSHIP_QUERY:
1347  sprintf (buf, "Member query");
1348  break;
1349 
1350  case ICMP6_MEMBERSHIP_REPORT:
1351  sprintf (buf, "Member report");
1352  break;
1353 
1354  case ICMP6_MEMBERSHIP_REDUCTION:
1355  sprintf (buf, "Member reduction");
1356  break;
1357 
1358  case ICMP6_ROUTER_RENUMBERING:
1359  sprintf (buf, "Router renum");
1360  break;
1361 
1362  case ICMP6_WRUREQUEST:
1363  sprintf (buf, "Who are you request");
1364  break;
1365 
1366  case ICMP6_WRUREPLY:
1367  sprintf (buf, "Who are you reply");
1368  break;
1369 
1370  case ND_ROUTER_SOLICIT:
1371  sprintf (buf, "Router solicitation");
1372  break;
1373 
1374  case ND_ROUTER_ADVERT:
1375  p += sprintf (p, "Router advert");
1376  if (len >= sizeof(icmp->radvert))
1377  p += sprintf (p, ", hop-lim %d, managed %d, lifetime %u\n"
1378  " reach-time %lu, retrans-time %lu",
1379  icmp->radvert.hop_limit, icmp->radvert.managed,
1380  intel16(icmp->radvert.lifetime),
1381  intel(icmp->radvert.reach_time),
1382  intel(icmp->radvert.retrans_time));
1383  else p += sprintf (p, ", short packet");
1384  break;
1385 
1386  case ND_NEIGHBOR_SOLICIT:
1387  sprintf (buf, "Neighbor solicitation, target %s",
1388  _inet6_ntoa(&icmp->nd_solic.target));
1389  opt = (const BYTE*)icmp + sizeof(icmp->nd_solic);
1390  opt = (const BYTE*)icmp6_options (opt, len - sizeof(icmp->nd_solic));
1391  break;
1392 
1393  case ND_NEIGHBOR_ADVERT:
1394  sprintf (buf, "Neighbor advert");
1395  break;
1396 
1397  case ND_REDIRECT:
1398  sprintf (buf, "Redirect");
1399  break;
1400 
1401  default:
1402  sprintf (buf, "Unknown type %d", type);
1403  break;
1404  }
1405 
1406  rc = dbug_printf ("ICMP6: %s, code %d\n"
1407  " chksum %04X (%s)\n",
1408  buf, icmp->unused.code, icmp->unused.checksum,
1409  _ip6_icmp_checksum(ip,icmp,len) ? "ok" : "ERROR");
1410  if (opt)
1411  rc += dbug_printf (" Opt: %s\n", opt);
1412  return (rc);
1413 }
1414 
1415 static int ip6_header_dump (const in6_Header *ip)
1416 {
1417  char src_type [20];
1418  char dst_type [20];
1419  int len;
1420 
1421  ip6_addr_type (src_type, &ip->source);
1422  ip6_addr_type (dst_type, &ip->destination);
1423 
1424  len = dbug_printf ("IP6: %s %s-> %s %s\n",
1425  ip6_src, src_type, ip6_dst, dst_type);
1426  len += dbug_printf (" ver %d, pri %d, flow %d,%d,%d, len %u, "
1427  "next-hdr %s (%u), hop-lim %d\n",
1428  ip->ver, ip->pri, ip->flow_lbl[0],
1429  ip->flow_lbl[1], ip->flow_lbl[2], intel16(ip->len),
1430  ip6_next_hdr(ip->next_hdr), ip->next_hdr, ip->hop_limit);
1431  return (len);
1432 }
1433 
1434 static unsigned ip6_payload_dump (const void *sock, const in6_Header *ip)
1435 {
1436  if (ip->next_hdr == IP6_NEXT_ICMP && debug.ICMP)
1437  return icmp6_dump (ip);
1438 
1439  if (ip->next_hdr == IP6_NEXT_UDP && debug.UDP)
1440  return udp6_dump ((const _udp_Socket*)sock, ip);
1441 
1442  if (ip->next_hdr == IP6_NEXT_TCP && debug.TCP)
1443  return tcp_dump ((const _tcp_Socket*)sock, (const in_Header*)ip);
1444 
1445 #if defined(USE_SCTP)
1446  if (ip->next_hdr == IP6_NEXT_SCTP && debug.SCTP)
1447  return sctp_dump (NULL, ip);
1448 #endif
1449 
1450  if (debug.IP) /* dump IPv6-network protocols as hex */
1451  {
1452  WORD len = intel16 (ip->len);
1453  len = min (len, MAX_IP6_DATA-sizeof(*ip));
1454  return dump_data (ip+1, len);
1455  }
1456  return (0);
1457 }
1458 #endif
1459 
1460 /*----------------------------------------------------------------------*/
1461 
1462 #if defined(USE_PPPOE)
1463 struct token {
1464  int v;
1465  const char *s;
1466  };
1467 
1468 struct token ppp_type2str[] = {
1469  { PPP_IP, "IP" },
1470  { PPP_IPV6, "IP6" },
1471  { PPP_IPX, "IPX" },
1472  { PPP_VJC, "VJC" },
1473  { PPP_VJNC, "VJNC" },
1474  { PPP_IPCP, "IPCP" },
1475  { PPP_IPXCP, "IPXCP" },
1476  { PPP_LCP, "LCP" },
1477  { PPP_LQR, "LQR" },
1478  { PPP_CCP, "CCP" },
1479  { PPP_PAP, "PAP" },
1480  { PPP_CHAP, "CHAP" },
1481  { PPP_CBCP, "CBCP" },
1482  { PPP_COMP, "COMP" },
1483  { 0, NULL }
1484  };
1485 
1486 /*
1487  * Convert a token value to a string; use "fmt" if not found.
1488  */
1489 static const char *tok2str (const struct token *lp, const char *fmt, int v)
1490 {
1491  static char buf[128];
1492 
1493  while (lp->s)
1494  {
1495  if (lp->v == v)
1496  return (lp->s);
1497  ++lp;
1498  }
1499  if (!fmt)
1500  fmt = "#%d";
1501  sprintf (buf, fmt, v);
1502  return (buf);
1503 }
1504 
1505 static const char *pppoe_get_tag (const BYTE *tag)
1506 {
1507  static char buf[100];
1508  char *p = buf;
1509  WORD type = *(WORD*)tag;
1510  int len = intel16 (*(WORD*)(tag+2));
1511 
1512  switch (type)
1513  {
1514  case PPPOE_TAG_END_LIST:
1515  return ("end");
1516 
1517  case PPPOE_TAG_SERVICE_NAME:
1518  len = min (len, SIZEOF(buf)-12);
1519  sprintf (buf, "service-name `%.*s'", len, tag+PPPOE_TAG_HDR_SIZE);
1520  break;
1521 
1522  case PPPOE_TAG_AC_NAME:
1523  len = min (len, SIZEOF(buf)-12);
1524  sprintf (buf, "AC-name `%.*s'", len, tag+PPPOE_TAG_HDR_SIZE);
1525  break;
1526 
1527  case PPPOE_TAG_AC_COOKIE:
1528  p += sprintf (p, "AC-cookie ");
1529  tag += PPPOE_TAG_HDR_SIZE;
1530  while (len > 0 && p < buf+sizeof(buf)-4)
1531  {
1532  p += sprintf (p, "%02X-", *tag & 255);
1533  tag++;
1534  len--;
1535  }
1536  *(p-1) = '\0';
1537  break;
1538 
1539  case PPPOE_TAG_HOST_UNIQ:
1540  p += sprintf (p, "host-uniq ");
1541  tag += PPPOE_TAG_HDR_SIZE;
1542  while (len > 0 && p < buf+sizeof(buf)-4)
1543  {
1544  p += sprintf (p, "%02X-", *tag & 255);
1545  tag++;
1546  len--;
1547  }
1548  *(p-1) = '\0';
1549  break;
1550 
1551  case PPPOE_TAG_VENDOR_SPES:
1552  sprintf (buf, "vendor spec ID %08lX", *(DWORD*)(tag+4));
1553  break;
1554 
1555  case PPPOE_TAG_RELAY_SESS:
1556  sprintf (buf, "relay session %d", *(WORD*)(tag+4));
1557  break;
1558 
1559  case PPPOE_TAG_HOST_URL:
1560  len = min (len, SIZEOF(buf)-12);
1561  sprintf (buf, "host URL `%.*s'", len, tag+PPPOE_TAG_HDR_SIZE);
1562  break;
1563 
1564  case PPPOE_TAG_MOTM:
1565  len = min (len, SIZEOF(buf)-12);
1566  sprintf (buf, "msg-of-the-minute `%.*s'",
1567  len, tag+PPPOE_TAG_HDR_SIZE);
1568  break;
1569 
1570  case PPPOE_TAG_IP_ROUTE_ADD:
1571  {
1572  char buf1[20], buf2[20], buf3[20];
1573  const char *dest_net = _inet_ntoa (buf1, intel(*(DWORD*)(tag+4)));
1574  const char *dest_mask = _inet_ntoa (buf2, intel(*(DWORD*)(tag+8)));
1575  const char *gateway = _inet_ntoa (buf3, intel(*(DWORD*)(tag+12)));
1576  DWORD metric = intel (*(DWORD*)(tag+16));
1577 
1578  sprintf (buf, "route add: %s %s %s / %lu",
1579  dest_net, dest_mask, gateway, metric);
1580  }
1581  break;
1582 
1583  case PPPOE_TAG_SERVICE_ERR:
1584  return ("service error");
1585 
1586  case PPPOE_TAG_AC_SYSTEM_ERR:
1587  return ("AC-system err");
1588 
1589  case PPPOE_TAG_GENERIC_ERR:
1590  return ("generic error");
1591 
1592  default:
1593  sprintf (buf, "unknown %04X", intel16(type));
1594  break;
1595  }
1596  return (buf);
1597 }
1598 
1599 const char *pppoe_get_code (WORD code)
1600 {
1601  switch (code)
1602  {
1603  case PPPOE_CODE_PADI:
1604  return ("PADI");
1605  case PPPOE_CODE_PADO:
1606  return ("PADO");
1607  case PPPOE_CODE_PADR:
1608  return ("PADR");
1609  case PPPOE_CODE_PADS:
1610  return ("PADS");
1611  case PPPOE_CODE_PADT:
1612  return ("PADT");
1613  case PPPOE_CODE_PADM:
1614  return ("PADM");
1615  case PPPOE_CODE_PADN:
1616  return ("PADN");
1617  default:
1618  return ("??");
1619  }
1620 }
1621 
1622 static __inline int pppoe_head_dump (const struct pppoe_Packet *pppoe,
1623  const char *proto)
1624 {
1625  WORD len = intel16 (pppoe->length);
1626 
1627  if (pppoe->ver != 1 || pppoe->type != 1 || len > PPPOE_MAX_DATA)
1628  {
1629  dbug_printf ("PPPOE: bogus header: ver %u, type %u, len %u\n",
1630  pppoe->ver, pppoe->type, len);
1631  return (0);
1632  }
1633  return dbug_printf ("PPPOE: %s, len %u, code %s (%04X), session %d\n",
1634  proto, len, pppoe_get_code(pppoe->code), pppoe->code,
1635  intel16(pppoe->session));
1636 }
1637 
1638 static int pppoe_disc_dump (const struct pppoe_Packet *pppoe)
1639 {
1640  WORD tlen = intel16 (pppoe->length);
1641  const BYTE *tags;
1642 
1643  if (!pppoe_head_dump(pppoe, "Discovery"))
1644  return (1);
1645 
1646  tags = (const BYTE*) &pppoe->data[0];
1647  while (tlen > 0)
1648  {
1649  WORD tag_len = intel16 (*(WORD*)(tags+2));
1650 
1651  dbug_printf (" tag: %s\n", pppoe_get_tag(tags));
1652  tlen -= (PPPOE_TAG_HDR_SIZE + tag_len);
1653  tags += (PPPOE_TAG_HDR_SIZE + tag_len);
1654  }
1655  return (1);
1656 }
1657 
1658 static int pppoe_sess_dump (const void *sock, const struct pppoe_Packet *pppoe)
1659 {
1660  WORD proto, len;
1661  const BYTE *buf;
1662 
1663  if (!pppoe_head_dump(pppoe, "Session"))
1664  return (1);
1665 
1666  len = intel16 (pppoe->length) - 2;
1667  proto = intel16 (*(WORD*)&pppoe->data[0]);
1668  buf = &pppoe->data[2];
1669 
1670  dbug_printf (" Protocol %04X (%s)\n", proto,
1671  tok2str(ppp_type2str,"%u??",proto));
1672 
1673  if (proto == PPP_IP)
1674  {
1675  const in_Header *ip = (const in_Header*)buf;
1676 
1677  _inet_ntoa (ip4_src, intel(ip->source));
1678  _inet_ntoa (ip4_dst, intel(ip->destination));
1679 
1680  ip4_dump (ip);
1681  return ip4_payload_dump (sock, ip);
1682  }
1683 
1684  if (proto == PPP_CCP)
1685  return ccp_dump (buf);
1686 
1687  if (proto == PPP_LCP)
1688  return lcp_dump (buf);
1689 
1690  if (proto == PPP_IPCP)
1691  return ipcp_dump (buf);
1692 
1693  return dump_data (buf, len);
1694 }
1695 #endif
1696 
1697 /*----------------------------------------------------------------------*/
1698 
1699 static const char *udp_tcp_checksum (const in_Header *ip,
1700  const udp_Header *udp,
1701  const tcp_Header *tcp)
1702 {
1703  tcp_PseudoHeader ph;
1704  int len;
1705 
1706  memset (&ph, 0, sizeof(ph));
1707  if (udp)
1708  {
1709  len = intel16 (udp->length);
1710  ph.protocol = UDP_PROTO;
1711  ph.checksum = CHECKSUM (udp, len);
1712  }
1713  else
1714  {
1715  len = intel16 (ip->length) - in_GetHdrLen (ip);
1716  ph.protocol = TCP_PROTO;
1717  ph.checksum = CHECKSUM (tcp, len);
1718  }
1719 
1720  ph.src = ip->source;
1721  ph.dst = ip->destination;
1722  ph.length = intel16 (len);
1723 
1724  if (CHECKSUM(&ph,sizeof(ph)) == 0xFFFF)
1725  return ("ok");
1726  return ("ERROR");
1727 }
1728 
1729 #if defined(USE_IPV6)
1730 static const char *udp_checksum (const in6_Header *ip, const udp_Header *udp)
1731 {
1732  if (_ip6_checksum(ip, IP6_NEXT_UDP, udp, intel16(ip->len)) == 0xFFFF)
1733  return ("ok");
1734  return ("ERROR");
1735 }
1736 
1737 static const char *tcp_checksum (const in6_Header *ip, const tcp_Header *tcp)
1738 {
1739  if (_ip6_checksum(ip, IP6_NEXT_TCP, tcp, intel16(ip->len)) == 0xFFFF)
1740  return ("ok");
1741  return ("ERROR");
1742 }
1743 #endif
1744 
1745 /*----------------------------------------------------------------------*/
1746 
1747 static BOOL is_dns_packet (WORD src_port, WORD dst_port)
1748 {
1749  WORD dns_port;
1750 
1751  if (!dbg_dns_details)
1752  return (FALSE);
1753 
1754  dns_port = intel16 (DOM_DST_PORT);
1755 
1756 #if 1
1757  if (src_port == dns_port || dst_port == dns_port)
1758  return (TRUE);
1759 #else
1760  if ((!outbound && src_port == dns_port) || /* Rx from DNS */
1761  ( outbound && dst_port == dns_port)) /* Tx to DNS */
1762  return (TRUE);
1763 #endif
1764  return (FALSE);
1765 }
1766 
1767 /*----------------------------------------------------------------------*/
1768 
1769 static int udp_dump (const _udp_Socket *sock, const in_Header *ip)
1770 {
1771  const char *chk_ok = "n/a";
1772  WORD iplen = intel16 (ip->length) - sizeof(*ip);
1773  const udp_Header *udp = (const udp_Header*) ((BYTE*)ip + in_GetHdrLen(ip));
1774  WORD udplen = intel16 (udp->length) - sizeof(*udp);
1775  const BYTE *data = (const BYTE*) (udp+1);
1776 
1777  if (udp->checksum && !frag_status)
1778  chk_ok = udp_tcp_checksum (ip, udp, NULL);
1779 
1780  if (frag_status || udplen > iplen)
1781  udplen = min (udplen, iplen);
1782 
1783  if (frag_status && !(frag_status & IS_FIRST)) /* is a fragment and not 1st */
1784  return dump_data (udp, iplen);
1785 
1786  dump_addr_port ("UDP", sock, ip);
1787 
1788  dbug_printf (" len %d, chksum %04X (%s)\n",
1789  intel16(udp->length), intel16(udp->checksum), chk_ok);
1790 
1791  if (udplen >= sizeof(struct DNS_Header) &&
1792  is_dns_packet(udp->srcPort,udp->dstPort))
1793  return dns_dump (data, udplen, 0);
1794  return dump_data (data, udplen);
1795 }
1796 
1797 #if defined(USE_IPV6)
1798 static int udp6_dump (const _udp_Socket *sock, const in6_Header *ip)
1799 {
1800  WORD iplen = intel16 (ip->len);
1801  const udp_Header *udp = (const udp_Header*) (ip + 1);
1802  WORD udplen = intel16 (udp->length) - sizeof(*udp);
1803  const BYTE *data = (const BYTE*) (udp + 1);
1804  const char *chk_ok = udp_checksum (ip, udp);
1805 
1806  udplen = min (udplen, iplen - sizeof(*udp));
1807 
1808  dump_addr6_port ("UDP", sock, ip);
1809 
1810  dbug_printf (" len %d, chksum %04X (%s)\n",
1811  intel16(udp->length), intel16(udp->checksum), chk_ok);
1812 
1813  if (udplen >= sizeof(struct DNS_Header) &&
1814  is_dns_packet(udp->srcPort,udp->dstPort))
1815  return dns_dump (data, udplen, 0);
1816  return dump_data (data, udplen);
1817 }
1818 #endif /* USE_IPV6 */
1819 
1820 /*----------------------------------------------------------------------*/
1821 
1822 static int tcp_dump (const _tcp_Socket *sock, const in_Header *ip)
1823 {
1824  const tcp_Header *tcp;
1825  const BYTE *data;
1826  const char *chk_ok = "n/a";
1827  WORD hlen;
1828  WORD iplen, dlen, olen;
1829  DWORD win, ack, seq;
1830  char flgBuf [4*8+1] = { 0 };
1831 
1832 #if defined(USE_IPV6)
1833  const in6_Header *ip6 = (const in6_Header*) ip;
1834 
1835  if (ip->ver == 6)
1836  {
1837  iplen = intel16 (ip6->len);
1838  tcp = (const tcp_Header*) (ip6 + 1);
1839  hlen = tcp->offset << 2;
1840  dlen = iplen - hlen;
1841  }
1842  else
1843 #endif
1844  {
1845  int j;
1846  iplen = intel16 (ip->length) - sizeof(*ip);
1847  j = in_GetHdrLen (ip);
1848  tcp = (const tcp_Header*) ((const BYTE*)ip + j);
1849  hlen = tcp->offset << 2;
1850  dlen = intel16 (ip->length) - j - hlen;
1851  }
1852 
1853  data = (const BYTE*) tcp + hlen;
1854  win = intel16 (tcp->window);
1855 
1856  if (frag_status || dlen > iplen)
1857  dlen = min (dlen, iplen);
1858 
1859  if (hlen < sizeof(*tcp))
1860  {
1861  dbug_write (" Bad header\n");
1862  return (0);
1863  }
1864 
1865  if (frag_status && !(frag_status & IS_FIRST))
1866  return dump_data (tcp, iplen);
1867 
1868  if (tcp->flags & tcp_FlagACK) strcat (flgBuf, " ACK");
1869  if (tcp->flags & tcp_FlagFIN) strcat (flgBuf, " FIN");
1870  if (tcp->flags & tcp_FlagSYN) strcat (flgBuf, " SYN");
1871  if (tcp->flags & tcp_FlagPUSH) strcat (flgBuf, " PSH");
1872  if (tcp->flags & tcp_FlagRST) strcat (flgBuf, " RST");
1873  if (tcp->flags & tcp_FlagURG) strcat (flgBuf, " URG");
1874  if (tcp->flags & tcp_FlagECN) strcat (flgBuf, " ECN");
1875  if (tcp->flags & tcp_FlagCWR) strcat (flgBuf, " CWR");
1876 
1877  if (!frag_status || (frag_status & IS_FIRST))
1878  {
1879 #if defined(USE_IPV6)
1880  if (ip->ver == 6)
1881  chk_ok = tcp_checksum (ip6, tcp);
1882  else
1883 #endif
1884  chk_ok = udp_tcp_checksum (ip, NULL, tcp);
1885  }
1886 
1887 #if defined(USE_IPV6)
1888  if (ip->ver == 6)
1889  dump_addr6_port ("TCP", sock, ip6);
1890  else
1891 #endif
1892  dump_addr_port ("TCP", sock, ip);
1893 
1894  if (sock)
1895  win <<= outbound ? sock->tx_wscale : sock->rx_wscale;
1896 
1897  ack = intel (tcp->acknum);
1898  seq = intel (tcp->seqnum);
1899 
1900  dbug_printf (" flags%s, win %lu, chksum %04X (%s), urg %u\n"
1901  " SEQ %10lu, ACK %10lu\n",
1902  flgBuf, win, intel16(tcp->checksum), chk_ok,
1903  intel16(tcp->urgent), seq, ack);
1904  if (sock)
1905  {
1906  BOOL in_seq_space;
1907  UINT state = sock->state;
1908  long delta_seq, delta_ack;
1909  long ms_left, ms_right;
1910 
1911  if (outbound)
1912  {
1913  if (state == tcp_StateSYNREC && sock->last_acknum[0] == 0)
1914  delta_ack = 0;
1915  else delta_ack = ack - sock->last_acknum[0];
1916 
1917  if (state == tcp_StateSYNSENT && sock->last_seqnum[0] == 0)
1918  delta_seq = 0;
1919  else delta_seq = seq - sock->last_seqnum[0];
1920 
1921  ((_tcp_Socket*)sock)->last_seqnum[0] = seq; /* !! unconst */
1922  ((_tcp_Socket*)sock)->last_acknum[0] = ack;
1923  }
1924  else
1925  {
1926  if (state == tcp_StateLISTEN && sock->last_seqnum[1] == 0)
1927  delta_seq = 0;
1928  else delta_seq = seq - sock->last_seqnum[1];
1929 
1930  if (state == tcp_StateSYNSENT && sock->last_acknum[1] == 0)
1931  delta_ack = 0;
1932  else delta_ack = ack - sock->last_acknum[1];
1933 
1934  ((_tcp_Socket*)sock)->last_seqnum[1] = seq;
1935  ((_tcp_Socket*)sock)->last_acknum[1] = ack;
1936  }
1937 
1938  if (sock->missed_seq[0] != sock->missed_seq[1] && !outbound)
1939  {
1940  /* show missing edges relative to his SEQ
1941  */
1942  ms_left = (long) (seq - sock->missed_seq[1]);
1943  ms_right = (long) (seq - sock->missed_seq[0]);
1944  in_seq_space = SEQ_BETWEEN (seq, sock->missed_seq[1], sock->missed_seq[0]);
1945  }
1946  else if (sock->missed_seq[0] != sock->missed_seq[1] && outbound)
1947  {
1948  /* show missing edges relative to our ACK
1949  */
1950  ms_left = (long) (ack - sock->missed_seq[1]);
1951  ms_right = (long) (ack - sock->missed_seq[0]);
1952  in_seq_space = FALSE;
1953  }
1954  else
1955  {
1956  ms_left = 0UL;
1957  ms_right = 0UL;
1958  in_seq_space = FALSE;
1959  }
1960 
1961  dbug_printf (" %-8.8s (dSEQ %10ld, dACK %10ld), MS %ld/%ld%s%s\n"
1962  " RCV.NXT %lu, SND.NXT %lu, SND.UNA %ld\n"
1963  " KC %d, vjSA %lu, vjSD %lu, CW %d, WW %d, RTO %d, ",
1964  tcpStateName(state), delta_seq, delta_ack, ms_left, ms_right,
1965  in_seq_space ? ", in-SEQ" : "",
1966  sock->unhappy ? ", Unhappy" : "",
1967  sock->recv_next, sock->send_next, sock->send_una,
1968  sock->karn_count, sock->vj_sa, sock->vj_sd,
1969  sock->cwindow, sock->wwindow, sock->rto);
1970  dbug_printf ("RTT-diff %s\n", RTT_str(sock->rtt_time, now));
1971  }
1972 
1973  olen = (WORD) (hlen - sizeof(*tcp));
1974  if (olen > 0)
1975  dump_tcp_opt (tcp+1, olen, ack);
1976 
1977  if (dlen > sizeof(struct DNS_Header) &&
1978  is_dns_packet(tcp->srcPort,tcp->dstPort))
1979  {
1980  WORD dns_len = intel16 (*(WORD*)data);
1981 
1982  if (dns_len == dlen-2)
1983  return dns_dump (data+2, dns_len, dns_len);
1984  }
1985  return dump_data (data, dlen);
1986 }
1987 
1988 /*----------------------------------------------------------------------*/
1989 
1990 static BOOL dbug_filter (void)
1991 {
1992 #if defined(NEED_PKT_SPLIT)
1993  const struct pkt_split *ps = outbound ? pkt_get_split_out() :
1994  pkt_get_split_in();
1995  for ( ; ps->data; ps++)
1996  {
1997  switch (ps->type)
1998  {
1999  case TYPE_ETHER_HEAD:
2000  if (!outbound)
2001  {
2002  const eth_Header *eth = (const eth_Header*) ps->data;
2003 
2004  if (filter.MAC && !match_link_destination(&eth->destination))
2005  return (FALSE);
2006  if (filter.LOOP && !memcmp(&eth->source,_eth_addr,_eth_mac_len))
2007  return (FALSE);
2008  }
2009  break;
2010 
2011  case TYPE_TOKEN_HEAD:
2012  if (!outbound)
2013  {
2014  const tok_Header *tok = (const tok_Header*) ps->data;
2015 
2016  if (filter.MAC && !match_link_destination(&tok->destination))
2017  return (FALSE);
2018  if (filter.LOOP && !memcmp(&tok->source,_eth_addr,_eth_mac_len))
2019  return (FALSE);
2020  }
2021  break;
2022 
2023  case TYPE_FDDI_HEAD:
2024  if (!outbound)
2025  {
2026  const fddi_Header *fddi = (const fddi_Header*) ps->data;
2027 
2028  if (filter.MAC && !match_link_destination(&fddi->destination))
2029  return (FALSE);
2030  if (filter.LOOP && !memcmp(&fddi->source,_eth_addr,_eth_mac_len))
2031  return (FALSE);
2032  }
2033  break;
2034 
2035  case TYPE_ARP:
2036  if (!outbound)
2037  {
2038  const arp_Header *arp = (const arp_Header*) ps->data;
2039 
2040  if (filter.ARP && !match_arp_rarp(arp))
2041  return (FALSE);
2042  if (filter.LOOP && !memcmp(&arp->srcEthAddr,_eth_addr,_eth_mac_len))
2043  return (FALSE);
2044  }
2045  return (debug.ARP);
2046 
2047  case TYPE_RARP:
2048  if (!outbound)
2049  {
2050  const rarp_Header *rarp = (const rarp_Header*) ps->data;
2051 
2052  if (filter.RARP && !match_arp_rarp(rarp))
2053  return (FALSE);
2054  if (filter.LOOP && !memcmp(&rarp->srcEthAddr,_eth_addr,_eth_mac_len))
2055  return (FALSE);
2056  }
2057  return (debug.RARP);
2058 
2059  case TYPE_PPPOE_SESS:
2060  case TYPE_PPPOE_DISC:
2061  break;
2062 
2063  case TYPE_IP4:
2064  if (!outbound)
2065  {
2066  const in_Header *ip = (const in_Header*) ps->data;
2067 
2068  if (filter.IP && !match_ip4_dest(ip))
2069  return (FALSE);
2070  if (filter.LOOP && intel(ip->source) == my_ip_addr)
2071  return (FALSE);
2072  }
2073  return (TRUE);
2074 
2075 #if defined(USE_IPV6)
2076  case TYPE_IP6:
2077  if (!outbound)
2078  {
2079  const in6_Header *ip6 = (const in6_Header*) ps->data;
2080 
2081  if (filter.IP && !match_ip6_dest(ip6))
2082  return (FALSE);
2083  if (filter.LOOP &&
2084  IN6_ARE_ADDR_EQUAL(&ip6->source, &in6addr_my_ip))
2085  return (FALSE);
2086  }
2087  return (TRUE);
2088 #endif
2089 
2090  default:
2091  return (TRUE); /* don't have filter for anything else */
2092  }
2093  }
2094 #endif /* NEED_PKT_SPLIT */
2095  return (TRUE); /* didn't match the component; allow it */
2096 }
2097 
2098 /*----------------------------------------------------------------------*/
2099 
2100 static const char *pcdbug_driver_ver (void)
2101 {
2102  static char buf[20];
2103  WORD major, minor, unused, build;
2104 
2105  if (!pkt_get_drvr_ver(&major,&minor,&unused,&build))
2106  return ("?");
2107 
2108 #if defined(WIN32) /* NPF.SYS/SwsVpkt.sys ver e.g. 3.1.0.22 */
2109  sprintf (buf, "%u.%u.%u.%u", major, minor, unused, build);
2110 #else
2111  sprintf (buf, "%d.%02d", major, minor);
2112 #endif
2113 
2114  return (buf);
2115 }
2116 
2117 static const char *pcdbug_api_ver (void)
2118 {
2119  static char buf[10];
2120  WORD ver;
2121 
2122  /* DOS: return pktdrvr API version (1.09 hopefully).
2123  * Win32: return NDIS version.
2124  */
2125  if (!pkt_get_api_ver(&ver))
2126  return ("?");
2127 
2128 #if defined(WIN32)
2129  sprintf (buf, "%d.%d", hiBYTE(ver), loBYTE(ver));
2130 #else
2131  if (ver >= 255) /* assumed to be MSB.LSB */
2132  sprintf (buf, "%d.%02d", hiBYTE(ver), loBYTE(ver));
2133  else sprintf (buf, "%d", loBYTE(ver));
2134 #endif
2135  return (buf);
2136 }
2137 
2138 /*----------------------------------------------------------------------*/
2139 
2140 static void print_driver_info (void)
2141 {
2142 #if defined(WIN32)
2143  /* What is needed to enable promiscous receive mode?*/
2144  #define PROMISC_RECV() (_pkt_rxmode & RXMODE_PROMISCOUS)
2145  #define CONFIG_RXMODE "winpkt.rxmode"
2146 
2147  const char *api = (_pkt_inf ? _pkt_inf->api_name : "??");
2148  const char *sys = (_pkt_inf ? _pkt_inf->sys_drvr_name : "??");
2149 
2150  dbug_printf ("%s\n"
2151  "Using: %s, \"%s\" (%s)\n"
2152  " %s ver %s, NDIS ver %s, mode 0x%02X\n",
2153  wattcpVersion(), api, _pktdrvrname, _pktdrvr_descr,
2154  sys, pcdbug_driver_ver(), pcdbug_api_ver(), _pkt_rxmode);
2155 
2156 #else
2157  #define PROMISC_RECV() (_pkt_rxmode >= RXMODE_PROMISCOUS)
2158  #define CONFIG_RXMODE "pkt.rxmode"
2159 
2160  dbug_printf ("%s\nPKTDRVR: \"%s\", ver %s, API ver %s, mode %d\n",
2161  wattcpVersion(), _pktdrvrname, pcdbug_driver_ver(),
2162  pcdbug_api_ver(), _pkt_rxmode);
2163 #endif
2164 }
2165 
2166 /*----------------------------------------------------------------------*/
2167 
2168 static void dbug_dump (const void *sock, const in_Header *ip,
2169  const char *fname, unsigned line, BOOL out)
2170 {
2171  static BOOL print_once = FALSE;
2172  int err;
2173 
2174  WATT_ASSERT (ip);
2175 
2176  outbound = out;
2177  frag_status = 0;
2178  now = set_timeout (0);
2179 
2180  if ((err = setjmp(dbg_jmp)) != 0)
2181  {
2182  (*_printf) ("\ndbug_dump: write failed; %s (%d)\n", strerror(err), err);
2183  dbug_close();
2184  goto quit;
2185  }
2186 
2187  if (pcap_mode && !use_ods)
2188  {
2189  int rc = 0;
2190 
2191  if (!dbg_file.stream || !(filter.NONE || dbug_filter()))
2192  goto quit;
2193 
2194  if (out && _eth_last.tx.size)
2195  rc = write_pcap_packet (MAC_HDR(ip), TRUE);
2196 
2197  else if (!out && _eth_last.rx.size)
2198  rc = write_pcap_packet (MAC_HDR(ip), FALSE);
2199 
2200  if (rc < 0)
2201  {
2202  (*_printf) (_LANG("\ndbug_dump: write failed; %s\n"), strerror(errno));
2203  dbug_close();
2204  }
2205  goto quit;
2206  }
2207 
2208  if (!print_once)
2209  {
2210  print_once = TRUE;
2211  print_driver_info();
2212 
2213 #if defined(PRINT_CPU_INFO)
2214  print_cpu_info();
2215 #endif
2216 
2217  if (!PROMISC_RECV() && filter.NONE)
2218  dbug_printf ("\nNB: receive-mode (%s = 0x%02X) is not suitable for "
2219  "receiving all traffic.\n", CONFIG_RXMODE, _pkt_rxmode);
2220  dbug_putc ('\n');
2221 
2222 #if !defined(__BORLANDC__) && 0 /* Some weird bug with Borland */
2223  _arp_debug_dump(); /* GvB 2002-09 now encapsuled in pcarp.c */
2224 
2225  if (_bootp_on || _dhcp_on || _rarp_on)
2226  dbug_printf (" Above routing data may be overridden by "
2227  "DHCP/BOOTP/RARP\n");
2228 #endif
2229  }
2230 
2231  if (!filter.NONE && !dbug_filter())
2232  goto quit;
2233 
2234  if (use_ods)
2235  dbug_putc ('\n'); /* !! Why do I need this? */
2236 
2237  dbug_printf ("\n%s: %s (%u), time %s%s\n",
2238  outbound ? "Transmitted" : "Received",
2239  fname, line, elapsed_str(now),
2240  is_looped(ip) ? ", Link-layer loop!" : "");
2241 
2242  /* Either PDCLASS_ETHER, PDCLASS_TOKEN, PDCLASS_FDDI or PDCLASS_ARCNET
2243  */
2244  if (!_pktserial)
2245  {
2246  union link_Packet *pkt = (union link_Packet*) MAC_HDR (ip);
2247  WORD type = MAC_TYP (ip);
2248 
2249  if (debug.MAC)
2250  link_head_dump (pkt);
2251 
2252  if (_pktdevclass == PDCLASS_ARCNET)
2253  {
2254  if (type == ARCNET_IP_1051 || /* Map to IANA proto-numbers */
2255  type == ARCNET_IP_1201)
2256  type = IP4_TYPE;
2257  else if (type == ARCNET_ARP_1051 ||
2258  type == ARCNET_ARP_1201)
2259  type = ARP_TYPE;
2260  else type = 0; /* unsupported */
2261  }
2262  else if (type == 0xFFFF)
2263  {
2264  dbug_printf ("IPX: unsupported\n");
2265  goto quit;
2266  }
2267  else if (intel16(type) < 0x600) /* type is IEEE 802.3 length field */
2268  {
2269  const llc_Header *llc = (const llc_Header*) (&pkt->eth.head + 1);
2270 
2271  /* !! could be NetBeui, VLAN etc. */
2272  dbug_printf ("LLC: unsupported\n");
2273  if (debug.LLC)
2274  dump_data (llc+1, intel16(type));
2275  goto quit;
2276  }
2277 
2278  if (type == ARP_TYPE)
2279  {
2280  arp_dump ((const arp_Header*)ip);
2281  goto quit;
2282  }
2283 
2284  if (type == RARP_TYPE)
2285  {
2286  rarp_dump ((const rarp_Header*)ip);
2287  goto quit;
2288  }
2289 
2290 #if defined(USE_PPPOE)
2291  if (type == PPPOE_DISC_TYPE)
2292  {
2293  pppoe_disc_dump ((const struct pppoe_Packet*)pkt->eth.data);
2294  goto quit;
2295  }
2296  if (type == PPPOE_SESS_TYPE)
2297  {
2298  pppoe_sess_dump (sock, (const struct pppoe_Packet*)pkt->eth.data);
2299  goto quit;
2300  }
2301 #endif
2302 
2303 #if defined(USE_IPV6)
2304  if (type == IP6_TYPE && ip->ver == 6)
2305  goto ip6_dmp;
2306 #endif
2307 
2308  if (type != IP4_TYPE)
2309  {
2310  const BYTE *data;
2311 
2312  if (!debug.MAC)
2313  dbug_printf ("Unknown type %04X\n",
2314  _pktdevclass == PDCLASS_ARCNET ? type : intel16(type));
2315 
2316  data = (const BYTE*)pkt + _pkt_ip_ofs;
2317  if (out && _eth_last.tx.size > _pkt_ip_ofs)
2318  dump_data (data, _eth_last.tx.size - _pkt_ip_ofs);
2319  else if (!out && _eth_last.rx.size > _pkt_ip_ofs)
2320  dump_data (data, _eth_last.rx.size - _pkt_ip_ofs);
2321  goto quit;
2322  }
2323  }
2324 
2325  if (ip->ver == 4)
2326  {
2327  _inet_ntoa (ip4_src, intel(ip->source));
2328  _inet_ntoa (ip4_dst, intel(ip->destination));
2329 
2330  ip4_dump (ip);
2331  ip4_payload_dump (sock, ip);
2332  }
2333 #if defined(USE_IPV6)
2334  else if (ip->ver == 6)
2335  {
2336  const struct in6_Header *ip6;
2337  const char *addr;
2338 
2339 ip6_dmp:
2340  ip6 = (const struct in6_Header*) ip;
2341  addr = _inet6_ntoa (ip6->source);
2342  strcpy (ip6_src, addr ? addr : "(null)");
2343 
2344  addr = _inet6_ntoa (ip6->destination);
2345  strcpy (ip6_dst, addr ? addr : "(null)");
2346 
2347  if (debug.IP)
2348  ip6_header_dump (ip6);
2349  ip6_payload_dump (sock, ip6);
2350  }
2351 #endif
2352  else
2353  {
2354  WORD len = intel16 (ip->length);
2355  dbug_printf ("IP?: ver %d\n", ip->ver);
2356  dump_data (ip, min(ETH_MAX_DATA,len));
2357  }
2358 
2359 quit:
2360  return;
2361 }
2362 
2363 /*----------------------------------------------------------------------*/
2364 
2365 static void trace_xmit_pkt (const void *sock, const in_Header *ip,
2366  const char *fname, unsigned line)
2367 {
2368  if (use_ods || dbg_file.stream)
2369  {
2370  in_dbug_dump = TRUE;
2371  dbug_dump (sock, ip, fname, line, TRUE);
2372  in_dbug_dump = FALSE;
2373  dbug_flush();
2374  }
2375 }
2376 
2377 static void trace_recv_pkt (const void *sock, const in_Header *ip,
2378  const char *fname, unsigned line)
2379 {
2380  if (use_ods || dbg_file.stream)
2381  {
2382  in_dbug_dump = TRUE;
2383  dbug_dump (sock, ip, fname, line, FALSE);
2384  in_dbug_dump = FALSE;
2385  dbug_flush();
2386  }
2387 }
2388 
2389 /*
2390  * Print IP-options
2391  */
2392 static void dump_ip_opt (const void *opt_p, int len)
2393 {
2394  const BYTE *opt = (const BYTE*) opt_p;
2395  const BYTE *start = opt;
2396  WORD val16;
2397  DWORD val32, ip, ts;
2398  int i, num, num_opt = 0;
2399 
2400  dbug_write (" Options:");
2401 
2402  while (opt < start+len && num_opt < 10)
2403  {
2404  switch (*opt) /* Note: IP-option includes copy/class bits */
2405  {
2406  case IPOPT_EOL:
2407  dbug_write (" EOL\n");
2408  return;
2409 
2410  case IPOPT_NOP:
2411  dbug_write (" NOP");
2412  opt++;
2413  continue;
2414 
2415  case IPOPT_RR:
2416  dbug_write (" RR");
2417  num = *(opt+1) - 3;
2418  num = min (num, len-1);
2419  for (i = 0; i < num; i += sizeof(DWORD))
2420  {
2421  val32 = intel (*(DWORD*)(opt+3+i));
2422  dbug_printf (" %s", _inet_ntoa(NULL,val32));
2423  }
2424  break;
2425 
2426  case IPOPT_TS:
2427  ip = intel (*(DWORD*)(opt+4));
2428  ts = intel (*(DWORD*)(opt+8));
2429  dbug_printf (" TS <%s/%lus..>", _inet_ntoa(NULL,ip), ts);
2430  break;
2431 
2432  case IPOPT_SECURITY:
2433  val32 = intel (*(DWORD*)(opt+2));
2434  dbug_printf (" SEC %08lX", val32);
2435  break;
2436 
2437  case IPOPT_SATID:
2438  val16 = intel16 (*(WORD*)(opt+2));
2439  dbug_printf (" SATID %04X", val16);
2440  break;
2441 
2442  case IPOPT_RA:
2443  val16 = intel16 (*(WORD*)(opt+2));
2444  dbug_printf (" RA %u", val16);
2445  break;
2446 
2447  case IPOPT_LSRR:
2448  case IPOPT_SSRR:
2449  dbug_write (*opt == IPOPT_LSRR ? " LSRR" : " SSRR");
2450  num = *(opt+1) - 3;
2451  num = min (num, len-1);
2452  for (i = 0; i < num; i += sizeof(DWORD))
2453  {
2454  DWORD route = intel (*(DWORD*)(opt+3+i));
2455  dbug_printf (" %s", _inet_ntoa(NULL,route));
2456  }
2457  break;
2458 
2459  default:
2460  dbug_printf (" opt %d?", *opt);
2461  }
2462  opt += *(opt+1);
2463  num_opt++;
2464  }
2465  dbug_putc ('\n');
2466 }
2467 
2468 /*
2469  * Print TCP-options
2470  */
2471 static void dump_tcp_opt (const void *opt_p, int len, DWORD ack)
2472 {
2473  const BYTE *opt = (const BYTE*) opt_p;
2474  const BYTE *start = opt;
2475  BYTE val8;
2476  WORD val16;
2477  DWORD val32;
2478  int i, num, num_opt = 0;
2479 
2480  dbug_write (" Options:");
2481 
2482  while (opt < start+len && num_opt < 10)
2483  {
2484  switch (*opt)
2485  {
2486  case TCPOPT_EOL:
2487  dbug_write (" EOL\n");
2488  return;
2489 
2490  case TCPOPT_NOP:
2491  dbug_write (" NOP");
2492  opt++;
2493  continue;
2494 
2495  case TCPOPT_MAXSEG:
2496  val16 = intel16 (*(WORD*)(opt+2));
2497  dbug_printf (" MSS %u", val16);
2498  break;
2499 
2500  case TCPOPT_WINDOW:
2501  val8 = opt[2];
2502  dbug_printf (" Wscale 2^%d", val8);
2503  break;
2504 
2505  case TCPOPT_SACK:
2506  dbug_write (" SACK ");
2507  num = (*(opt+1) - 2) / SIZEOF(DWORD);
2508  num = min (num, len/SIZEOF(DWORD));
2509 
2510  for (i = 0; i < num; i++)
2511  {
2512  DWORD origin = intel (*(DWORD*)(opt+2+4*i));
2513  DWORD relsize = intel (*(DWORD*)(opt+6+4*i));
2514  dbug_printf ("blk %d {%ld/%ld}, ", i+1,
2515  (long)(ack-origin-1),
2516  (long)(ack-origin+relsize));
2517  }
2518  break;
2519 
2520  case TCPOPT_SACK_PERM:
2521  dbug_write (" SACK-OK");
2522  break;
2523 
2524  case TCPOPT_ECHO:
2525  val32 = intel (*(DWORD*)(opt+2));
2526  dbug_printf (" Echo %lu", val32);
2527  break;
2528 
2529  case TCPOPT_CHKSUM_REQ:
2530  val8 = opt[2];
2531  dbug_printf (" ChkReq %d", val8);
2532  break;
2533 
2534  case TCPOPT_CHKSUM_DAT:
2535  num = opt[1];
2536  dbug_write (" ChkDat ");
2537  for (i = 0; i < num; i++)
2538  dbug_printf ("%02X", opt[2+i]);
2539  break;
2540 
2541  case TCPOPT_ECHOREPLY:
2542  val32 = intel (*(DWORD*)(opt+2));
2543  dbug_printf (" Echoreply %lu", val32);
2544  break;
2545 
2546  case TCPOPT_TIMESTAMP:
2547  val32 = intel (*(DWORD*)(opt+2));
2548  dbug_printf (" TS <%lu", val32);
2549  val32 = intel (*(DWORD*)(opt+6));
2550  dbug_printf ("/%lu>", val32);
2551  break;
2552 
2553  case TCPOPT_CC:
2554  val32 = intel (*(DWORD*)(opt+2));
2555  dbug_printf (" CC %lu", val32);
2556  break;
2557 
2558  case TCPOPT_CCNEW:
2559  val32 = intel (*(DWORD*)(opt+2));
2560  dbug_printf (" CCnew %lu", val32);
2561  break;
2562 
2563  case TCPOPT_CCECHO:
2564  val32 = intel (*(DWORD*)(opt+2));
2565  dbug_printf (" CCecho %lu", val32);
2566  break;
2567 
2568  case TCPOPT_SIGNATURE:
2569  if (opt > (const BYTE*)opt_p)
2570  dbug_write ("\n ");
2571  dbug_write (" MD5 ");
2572  for (i = 0; i < TCPOPT_SIGN_LEN; i++)
2573  dbug_printf ("%02X ", opt[2+i]);
2574  break;
2575 
2576  default:
2577  dbug_printf (" opt %d?", *opt);
2578  }
2579  opt += *(opt+1);
2580  num_opt++;
2581  }
2582  dbug_putc ('\n');
2583 }
2584 
2585 /*----------------------------------------------------------------------*/
2586 
2587 static DWORD dump_data (const void *data_p, UINT datalen)
2588 {
2589  const BYTE *data = (const BYTE*) data_p;
2590  UINT ofs;
2591  DWORD len = 0;
2592 
2593  if (!dbg_mode_all)
2594  return (1);
2595 
2596  for (ofs = 0; ofs < datalen; ofs += 16)
2597  {
2598  UINT j;
2599 
2600  if (ofs == 0)
2601  len += dbug_printf ("%u:%s%04X: ", datalen,
2602  datalen > 9999 ? " " :
2603  datalen > 999 ? " " :
2604  datalen > 99 ? " " :
2605  datalen > 9 ? " " :
2606  " ",
2607  ofs);
2608  else len += dbug_printf (" %04X: ", ofs);
2609 
2610  for (j = 0; j < 16 && j+ofs < datalen; j++)
2611  len += dbug_printf ("%02X%c", (unsigned)data[j+ofs],
2612  j == 7 ? '-' : ' '); /* no beeps */
2613 
2614  for ( ; j < 16; j++) /* pad line to 16 positions */
2615  len += dbug_write (" ");
2616 
2617  for (j = 0; j < 16 && j+ofs < datalen; j++)
2618  {
2619  int ch = data[j+ofs];
2620 
2621  if (ch < ' ') /* non-printable */
2622  dbug_putc ('.');
2623  else dbug_putc (ch);
2624  len++;
2625  }
2626  dbug_putc ('\n');
2627  len++;
2628  }
2629  return (len);
2630 }
2631 
2632 /*----------------------------------------------------------------------*/
2633 
2634 static void set_debug_file (const char *value)
2635 {
2636  _strlcpy (dbg_name, value, sizeof(dbg_name)-1);
2637 }
2638 
2639 static void set_debug_mode (const char *value)
2640 {
2641  if (!stricmp(value,"ALL"))
2642  dbg_mode_all = 1;
2643  if (!stricmp(value,"HEADER"))
2644  dbg_mode_all = 0;
2645 }
2646 
2647 static void set_debug_filter (const char *value)
2648 {
2649  char val[80];
2650 
2651  _strlcpy (val, value, sizeof(val));
2652  strupr (val);
2653 
2654  if (strstr(val,"ALL"))
2655  {
2656  memset (&filter, 1, sizeof(filter));
2657  filter.NONE = FALSE;
2658  }
2659  else if (strstr(val,"NONE"))
2660  {
2661  memset (&filter, 0, sizeof(filter));
2662  filter.NONE = TRUE;
2663  }
2664  else
2665  {
2666  filter.NONE = FALSE;
2667  filter.MAC = (strstr(val,"ETH" ) != NULL) || (strstr(val,"MAC") != NULL);
2668  filter.ARP = (strstr(val,"ARP" ) != NULL);
2669  filter.RARP = (strstr(val,"RARP") != NULL);
2670  filter.IP = (strstr(val,"IP" ) != NULL);
2671  filter.BCAST = (strstr(val,"BCAST") != NULL);
2672  filter.MCAST = (strstr(val,"MCAST") != NULL);
2673  filter.LOOP = (strstr(val,"LOOP") != NULL);
2674  }
2675 }
2676 
2677 static void set_debug_proto (const char *value)
2678 {
2679  char val[80];
2680 
2681  _strlcpy (val, value, sizeof(val));
2682  strupr (val);
2683 
2684  if (!strcmp(val,"ALL"))
2685  memset (&debug, 1, sizeof(debug));
2686  else
2687  {
2688  memset (&debug, 0, sizeof(debug));
2689  debug.MAC = (strstr(val,"ETH" ) != NULL) || (strstr(val,"MAC") != NULL);
2690  debug.LLC = (strstr(val,"LLC" ) != NULL);
2691  debug.ARP = (strstr(val,"ARP" ) != NULL);
2692  debug.RARP = (strstr(val,"RARP") != NULL);
2693  debug.IP = (strstr(val,"IP" ) != NULL);
2694  debug.TCP = (strstr(val,"TCP" ) != NULL);
2695  debug.UDP = (strstr(val,"UDP" ) != NULL);
2696  debug.ICMP = (strstr(val,"ICMP") != NULL);
2697  debug.IGMP = (strstr(val,"IGMP") != NULL);
2698  debug.SCTP = (strstr(val,"SCTP") != NULL);
2699  }
2700 }
2701 
2702 static void W32_CALL dbug_cfg_parse (const char *name, const char *value)
2703 {
2704  static const struct config_table debug_cfg[] = {
2705  { "FILE", ARG_FUNC, (void*)set_debug_file },
2706  { "MODE", ARG_FUNC, (void*)set_debug_mode },
2707  { "LINEBUF",ARG_ATOI, (void*)&dbg_linebuf },
2708  { "FILTER", ARG_FUNC, (void*)set_debug_filter },
2709  { "PROTO", ARG_FUNC, (void*)set_debug_proto },
2710  { "STAT", ARG_ATOI, (void*)&dbg_print_stat },
2711  { "DNS", ARG_ATOI, (void*)&dbg_dns_details },
2712  { "PCAP", ARG_ATOI, (void*)&pcap_mode },
2713  { NULL, 0, NULL }
2714  };
2715  if (!parse_config_table(&debug_cfg[0], "DEBUG.", name, value) && prev_hook)
2716  (*prev_hook) (name, value);
2717 }
2718 
2719 #if defined(WIN32)
2720  static char ods_buf [4000];
2721  static char *ods_ptr = ods_buf;
2722 
2723  static int flush_ods (void)
2724  {
2725  WATT_ASSERT (ods_ptr >= ods_buf);
2726  WATT_ASSERT (ods_ptr < ods_buf + sizeof(ods_buf) - 2);
2727 
2728  if (ods_ptr == ods_buf)
2729  return (0);
2730 
2731  if (ods_ptr[-2] != '\r' && ods_ptr[-1] != '\n')
2732  {
2733  *ods_ptr++ = '\r';
2734  *ods_ptr++ = '\n';
2735  }
2736  *ods_ptr = '\0';
2737  ods_ptr = ods_buf; /* restart buffer */
2738  OutputDebugStringA (ods_buf);
2739  return (1);
2740  }
2741 #endif
2742 
2743 
2744 int MS_CDECL dbug_printf (const char *format, ...)
2745 {
2746  va_list arg;
2747  int len = 0;
2748 
2749 #if defined(WIN32)
2750  if (use_ods)
2751  {
2752  len = ods_buf + sizeof(ods_buf) - ods_ptr - 1; /* length left on ods_buf[] */
2753  va_start (arg, format);
2754  if (len > 2)
2755  len = VSNPRINTF (ods_ptr, len, format, arg);
2756  va_end (arg);
2757  if (len > 0)
2758  ods_ptr += len;
2759  return (len);
2760  }
2761 #endif
2762 
2763  /* don't let anyone else write if pcap-mode
2764  */
2765  if (dbg_file.stream && !pcap_mode)
2766  {
2767  va_start (arg, format);
2768  len = vfprintf (dbg_file.stream, format, arg);
2769  va_end (arg);
2770  if (in_dbug_dump && ferror(dbg_file.stream))
2771  longjmp (dbg_jmp, errno);
2772  }
2773  return (len);
2774 }
2775 
2776 int dbug_write (const char *buf)
2777 {
2778  int len = -1;
2779 
2780 #if defined(WIN32)
2781  if (use_ods)
2782  {
2783  len = strlen (buf);
2784  len = min (len, ods_buf + sizeof(ods_buf) - ods_ptr - 1);
2785  memcpy (ods_ptr, buf, len);
2786  ods_ptr += len;
2787  return (len);
2788  }
2789 #endif
2790 
2791  if (dbg_file.stream && !pcap_mode)
2792  {
2793  len = fputs (buf, dbg_file.stream);
2794  if (in_dbug_dump && (len < 0 || ferror(dbg_file.stream)))
2795  longjmp (dbg_jmp, errno);
2796  }
2797  return (len);
2798 }
2799 
2800 int dbug_putc (int c)
2801 {
2802 #if defined(WIN32)
2803  if (use_ods)
2804  {
2805  WATT_ASSERT (ods_ptr);
2806  WATT_ASSERT (ods_ptr >= ods_buf);
2807  WATT_ASSERT (ods_ptr <= ods_buf + sizeof(ods_buf) - 2);
2808 
2809  if (c == '\n')
2810  {
2811  *ods_ptr++ = '\r';
2812  *ods_ptr++ = '\n';
2813  return flush_ods();
2814  }
2815  *ods_ptr++ = c;
2816  return (1);
2817  }
2818 #endif
2819  return fputc (c, dbg_file.stream);
2820 }
2821 
2822 int db_write_raw (const char *buf) /* old name */
2823 {
2824  return dbug_write (buf);
2825 }
2826 
2827 static void dbug_close (void)
2828 {
2829  if (dbg_file.stream &&
2830  dbg_file.stream != stdout && dbg_file.stream != stderr)
2831  {
2832 #if defined(USE_GZIP)
2833  if (use_gzip)
2834  gzclose (dbg_file.gz_stream);
2835  else
2836 #endif
2837  fclose (dbg_file.stream);
2838  }
2839  dbg_file.stream = NULL;
2840 }
2841 
2842 void dbug_flush (void)
2843 {
2844 #if defined(WIN32)
2845  if (use_ods)
2846  flush_ods();
2847  else
2848 #endif
2849  if (dbg_file.stream && !pcap_mode)
2850  {
2851  fflush (dbg_file.stream);
2852 #if 0
2853  if (dbg_file.stream != stdout && /* no point */
2854  dbg_file.stream != stderr)
2855  _dos_commit (fileno(dbg_file.stream));
2856 #endif
2857  }
2858 }
2859 
2860 /*
2861  * Public initialisation
2862  */
2863 void W32_CALL dbug_init (void)
2864 {
2865  static BOOL init = FALSE;
2866 
2867  if (init)
2868  {
2869  outsnl ("dbug_init() already called");
2870  return;
2871  }
2872  init = TRUE;
2873  prev_hook = usr_init;
2874  usr_init = dbug_cfg_parse;
2875  debug_xmit = trace_xmit_pkt;
2876  debug_recv = trace_recv_pkt;
2877 
2878 #if defined(USE_BSD_API)
2879  _sock_dbug_init();
2880 #endif
2881 
2882  if (_watt_is_init && !dbg_file.stream)
2883  fprintf (stderr, "`dbug_init()' called after `sock_init()'.\n\7");
2884  else memset (&filter, 0, sizeof(filter));
2885 }
2886 
2887 
2895 static void dbug_exit (void)
2896 {
2897  int (MS_CDECL *save_printf) (const char*, ...) = _printf;
2898 
2899  if (!_watt_fatal_error) /* an assert isn't fatal */
2900  {
2901  if (dbg_file.stream && !pcap_mode)
2902  _printf = dbug_printf; /* dump to wattcp.dbg */
2903 #if defined(USE_BSD_API)
2904  else if (_sock_dbug_active())
2905  _printf = _sock_debugf; /* dump to wattcp.sk */
2906 #endif
2907  else _printf = NULL;
2908 
2909  if (_printf)
2910  {
2911 #if defined(USE_STATISTICS)
2912  if (dbg_print_stat)
2913  {
2914  //_arp_debug_dump(); /* Moved from startup to closing */
2915  _arp_cache_dump();
2916  print_all_stats();
2917  }
2918 #endif
2919 
2920  if (_watt_cbroke)
2921  dbug_printf ("\nTerminating on SIGINT\n");
2922  if (_watt_assert_buf[0])
2923  dbug_printf ("\n%s\n", _watt_assert_buf);
2924  _watt_assert_buf[0] = '\0';
2925  }
2926  }
2927  dbug_close();
2928 
2929 #if defined(USE_GZIP)
2930  if (use_gzip && !_watt_fatal_error)
2931  {
2932  struct stat st;
2933 
2934  if (stat(dbg_name,&st) == 0 && st.st_size > 0)
2935  (*_printf) (" \ngzip compression: %lu raw, %lu compressed (%lu%%)\n",
2936  bytes_raw, (DWORD)st.st_size,
2937  (DWORD)(100 - (100*st.st_size)/bytes_raw));
2938  }
2939 #endif
2940 
2941  _printf = save_printf;
2942 }
2943 
2944 
2954 static const char *dns_opcodes[16] = {
2955  "standard", /* DNS_OP_QUERY */
2956  "inverse", /* DNS_OP_INVERSE */
2957  "server status",
2958  "op 3??",
2959  "op 4??",
2960  "update",
2961  "op 6??",
2962  "op 7??",
2963  "op 8??",
2964  "op 9??",
2965  "op 10??",
2966  "op 11??",
2967  "op 12??",
2968  "op 13??",
2969  "op 14??",
2970  "op 15??"
2971  };
2972 
2973 static const char *dns_responses[16] = {
2974  "no error", /* DNS_SRV_OK */
2975  "format error", /* DNS_SRV_FORM */
2976  "server error", /* DNS_SRV_FAIL */
2977  "NXDOMAIN", /* DNS_SRV_NAME */
2978  "not implemented", /* DNS_SRV_NOTIMP */
2979  "service refused", /* DNS_SRV_REFUSE */
2980  "resp 6??",
2981  "resp 7??",
2982  "resp 8??",
2983  "resp 9??",
2984  "resp 10??",
2985  "resp 11??",
2986  "resp 12??",
2987  "resp 13??",
2988  "resp 14??",
2989  "resp 15??"
2990  };
2991 
2992 /*
2993  * dns_query()
2994  *
2995  * Return a string describing the numeric value of a DNS query type
2996  */
2997 static __inline const char *dns_query (WORD type)
2998 {
2999  switch (type)
3000  {
3001  case T_A:
3002  return ("A");
3003  case T_AAAA:
3004  return ("AAAA");
3005  case T_NS:
3006  return ("NS");
3007  case T_CNAME:
3008  return ("CNAME");
3009  case T_PTR:
3010  return ("PTR");
3011  case T_HINFO:
3012  return ("HINFO");
3013  case T_MX:
3014  return ("MX");
3015  case T_MB:
3016  return ("MB");
3017  case T_SOA:
3018  return ("SOA");
3019  case T_SRV:
3020  return ("SRV");
3021  case T_AXFR:
3022  return ("AXFR");
3023  case T_TXT:
3024  return ("TXT");
3025  case T_WINS:
3026  return ("WINS");
3027  case T_WINSR:
3028  return ("WINS-R");
3029  case T_ANY:
3030  return ("ANY");
3031  default:
3032  return ("??");
3033  }
3034 }
3035 
3036 /*
3037  * Parse DNS packet and dump fields
3038  */
3039 static unsigned dns_dump (const BYTE *bp, unsigned length, unsigned dns_len)
3040 {
3041  #define CHK_BOGUS(p) if (p > bp+length) goto bogus
3042 
3043  const struct DNS_Header *dns = (const struct DNS_Header*) bp;
3044  const BYTE *body = (const BYTE*)bp + sizeof(*dns);
3045  const BYTE *end_p = (const BYTE*)bp + length;
3046  const char *opcode = dns_opcodes [dns->dns_fl_opcode];
3047  const char *rcode = dns_responses [dns->dns_fl_rcode];
3048  int i, t;
3049  unsigned len = 0;
3050 
3051  if (!dbg_mode_all)
3052  return (1);
3053 
3054  dbug_write ("DNS: ");
3055  if (dns_len)
3056  dbug_printf ("length %u, ", dns_len);
3057 
3058  len += dbug_printf ("Ident %u, %s, Opcode: %s, %sAuth\n",
3059  intel16(dns->dns_id), dns->dns_fl_qr ?
3060  "Response" : "Query", opcode ? opcode : "??",
3061  !dns->dns_fl_ad ? "Non-" : "");
3062 
3063  if (!dns->dns_fl_qr && rcode) /* Response code only in responses */
3064  rcode = "";
3065 
3066  len += dbug_printf (" auth answer %d, truncated %d, rec-req %d, "
3067  "rec-avail %d, %s\n",
3068  dns->dns_fl_aa, dns->dns_fl_tc, dns->dns_fl_rd,
3069  dns->dns_fl_ra, rcode ? rcode : "??");
3070  if (!opcode || !rcode)
3071  goto bogus;
3072 
3073  if (length <= sizeof(*dns)) /* no body present */
3074  return (length);
3075 
3076  /* Do the question part of the packet.
3077  */
3078  i = intel16 (dns->dns_num_q);
3079 
3080  while (i > 0)
3081  {
3082  WORD qtype, qclass;
3083 
3084  dbug_write (" Question: query name ");
3085  body = dns_labels (body, bp, end_p);
3086  CHK_BOGUS (body);
3087 
3088  qtype = intel16 (*(WORD*)body); body += sizeof(qtype);
3089  qclass = intel16 (*(WORD*)body); body += sizeof(qclass);
3090 
3091  dbug_printf (" query type %d (%s), class %d\n",
3092  qtype, dns_query(qtype), qclass);
3093  i--;
3094  }
3095 
3096  /* Dump the resource records for the answers
3097  */
3098  i = intel16 (dns->dns_num_ans);
3099  t = i;
3100  while (i > 0)
3101  {
3102  dbug_printf (" Answer %d: ", t-i+1);
3103  body = dns_resource (body, bp, end_p);
3104  CHK_BOGUS (body);
3105  i--;
3106  }
3107 
3108  /* Dump the resource records for the authoritative answers
3109  */
3110  i = intel16 (dns->dns_num_auth);
3111  t = i;
3112  while (i > 0)
3113  {
3114  dbug_printf (" Auth %d: ", t-i+1);
3115  body = dns_resource (body, bp, end_p);
3116  CHK_BOGUS (body);
3117  i--;
3118  }
3119 
3120  /* Dump the resource records for the additional info
3121  */
3122  i = intel16 (dns->dns_num_add);
3123  t = i;
3124  while (i > 0)
3125  {
3126  dbug_printf (" Additional %d: ", t-i+1);
3127  body = dns_resource (body, bp, end_p);
3128  CHK_BOGUS (body);
3129  i--;
3130  }
3131  return (len);
3132 
3133 bogus:
3134  dbug_printf (" Looks like a bogus packet; length %d\n", length);
3135  return (len);
3136 }
3137 
3138 /*
3139  * Print the contents of a resource record
3140  */
3141 static const BYTE *dns_resource (const BYTE *p, const BYTE *bp, const BYTE *ep)
3142 {
3143  DWORD ttl, val;
3144  WORD qtype, qclass, reslen;
3145  const char *ip;
3146 
3147  dbug_write ("server name: ");
3148  p = dns_labels (p, bp, ep);
3149 
3150  /* Do query type, class, ttl and resource length
3151  */
3152  qtype = intel16 (*(WORD*)p); p += sizeof(qtype);
3153  qclass = intel16 (*(WORD*)p); p += sizeof(qclass);
3154  ttl = intel (*(DWORD*)p); p += sizeof(ttl);
3155  reslen = intel16 (*(WORD*)p); p += sizeof(reslen);
3156 
3157  dbug_printf (" type %d (%s), class %d, TTL %s, length %u\n",
3158  qtype, dns_query(qtype), qclass, hms_str(ttl), reslen);
3159 
3160  /* Do resource data.
3161  */
3162  switch (qtype)
3163  {
3164  case T_A: /* A record; ip4 address(es) */
3165  if (reslen == 4)
3166  {
3167  ip = _inet_ntoa (NULL, intel(*(DWORD*)p));
3168  dbug_printf (" IP4 address: %s\n", ip);
3169  }
3170  else if (reslen == 7)
3171  {
3172  ip = _inet_ntoa (NULL, intel(*(DWORD*)p));
3173  dbug_printf (" IP4 address: %s, proto %u, port %u\n",
3174  ip, *(p+4), intel16(*(WORD*)(p+5)));
3175  }
3176  else
3177  dbug_printf (" IP4 address: bogus reslen %u\n", reslen);
3178 
3179  p += reslen;
3180  break;
3181 
3182 #if defined(USE_IPV6)
3183  case T_AAAA: /* AAAA record; ip6 address(es) */
3184  while (reslen >= sizeof(ip6_address))
3185  {
3186  const char *addr = _inet6_ntoa ((const void*)p);
3187  dbug_printf (" IP6 address: %s\n", addr);
3188  p += sizeof (ip6_address);
3189  reslen -= sizeof (ip6_address);
3190  }
3191  break;
3192 #endif
3193  case T_NS: /* NS record; Name Server */
3194  dbug_write (" auth host: ");
3195  p = dns_labels (p, bp, ep);
3196  break;
3197 
3198  case T_MX: /* MX record; Mail Exchange */
3199  dbug_printf (" mail exchange host (%u): ", intel16(*(WORD*)p));
3200  p += 2;
3201  p = dns_labels (p, bp, ep);
3202  break;
3203 
3204  case T_CNAME: /* CNAME record; canonical name */
3205  dbug_write (" canon host: ");
3206  p = dns_labels (p, bp, ep);
3207  break;
3208 
3209  case T_PTR: /* PTR record; hostname for IP */
3210  dbug_write (" host name: ");
3211  p = dns_labels (p, bp, ep);
3212  break;
3213 
3214  case T_TXT: /* TXT record; 1 or more text labels */
3215  dbug_write (" TXT info: ");
3216  p = dns_labels (p, bp, ep);
3217  break;
3218 
3219  case T_WINS: /* WINS record; */
3220  dbug_write (" WINS name: ");
3221  p = dns_labels (p, bp, ep);
3222  break;
3223 
3224  case T_WINSR: /* WINS-reverse record; */
3225  dbug_write (" WINS-R addr: ");
3226  p = dns_labels (p, bp, ep);
3227  break;
3228 
3229  case T_SOA:
3230  dbug_write (" SOA: ");
3231  p = dns_labels (p, bp, ep);
3232  if (p < ep)
3233  {
3234  dbug_write (" ");
3235  p = dns_labels (p, bp, ep);
3236 
3237  val = intel (*(DWORD*)p);
3238  p += 4;
3239  dbug_printf (" serial %lu", val);
3240 
3241  val = intel (*(DWORD*)p);
3242  p += 4;
3243  dbug_printf (", refresh %s", hms_str(val));
3244 
3245  val = intel (*(DWORD*)p);
3246  p += 4;
3247  dbug_printf (", retry %s\n", hms_str(val));
3248 
3249  val = intel (*(DWORD*)p);
3250  p += 4;
3251  dbug_printf (" expire %s", hms_str(val));
3252 
3253  val = intel (*(DWORD*)p);
3254  p += 4;
3255  dbug_printf (", minimum %s\n", hms_str(val));
3256  }
3257  break;
3258 
3259  default:
3260  p += reslen;
3261  }
3262  return (p);
3263 }
3264 
3265 /*
3266  * Recursively parse a label entry in a DNS packet
3267  * 'p' points to a DNS label.
3268  * 'bp' points to a beginning of DNS header.
3269  */
3270 static const BYTE *dns_labels (const BYTE *p, const BYTE *bp, const BYTE *ep)
3271 {
3272  while (1)
3273  {
3274  BYTE count = *p++;
3275 
3276  if (count >= 0xC0)
3277  {
3278  /* There's a pointer (rel to 'bp' start) in this label.
3279  * Let's grab the 14 low-order bits and run with them.
3280  */
3281  WORD offset = (WORD) (((unsigned)(count - 0xC0) << 8) + *p++);
3282 
3283  /* dbug_printf ("(ofs %u) ", offset); !! show where the offset is */
3284  dns_labels (bp+offset, bp, ep);
3285  return (p);
3286  }
3287  if (count == 0)
3288  break;
3289 
3290  while (count > 0)
3291  {
3292  if (p <= ep)
3293  {
3294  dbug_putc (*p++);
3295  count--;
3296  }
3297  else
3298  {
3299  dbug_write ("\nPacket length exceeded\n");
3300  return (p);
3301  }
3302  }
3303  dbug_putc ('.');
3304  }
3305  dbug_putc ('\n');
3306  return (p);
3307 }
3308 
3309 
3310 #if defined(USE_PPPOE)
3311 
3312 /* NCP Codes */
3313 enum ncp_codes {
3314  CONFREQ = 1,
3315  CONFACK = 2,
3316  CONFNAK = 3,
3317  CONFREJ = 4,
3318  TERMREQ = 5,
3319  TERMACK = 6,
3320  CODEREJ = 7,
3321  PROTREJ = 8,
3322  ECHOREQ = 9,
3323  ECHOREP = 10,
3324  DISCARD = 11
3325  };
3326 
3327 enum lcp_options {
3328  LCP_RESERVED = 0,
3329  LCP_MRU = 1,
3330  LCP_ASYNCMAP = 2,
3331  LCP_AUTHPROTO = 3,
3332  LCP_QUALPROTO = 4,
3333  LCP_MAGICNUM = 5,
3334  LCP_PCOMP = 7,
3335  LCP_ACFCOMP = 8,
3336  LCP_CALLBACK = 13
3337  };
3338 
3339 enum ipcp_options {
3340  IPCP_RESERVED = 0,
3341  IPCP_ADDRS = 1,
3342  IPCP_COMPRTYPE = 2,
3343  IPCP_ADDR = 3,
3344  IPCP_MS_DNS1 = 129,
3345  IPCP_MS_WINS1 = 130,
3346  IPCP_MS_DNS2 = 131,
3347  IPCP_MS_WINS2 = 132,
3348  };
3349 
3350 static const struct token ncp_code2str[] = { /* LCP/IPCP codes */
3351  { CONFREQ, "ConfReq" },
3352  { CONFACK, "ConfAck" },
3353  { CONFNAK, "ConfNak" },
3354  { CONFREJ, "ConfRej" },
3355  { TERMREQ, "TermReq" },
3356  { TERMACK, "TermAck" },
3357  { CODEREJ, "CodeRej" },
3358  { PROTREJ, "ProtRej" },
3359  { ECHOREQ, "EchoReq" },
3360  { ECHOREP, "EchoRep" },
3361  { DISCARD, "Discard" },
3362  { 0, NULL }
3363  };
3364 
3365 static const struct token lcp_option2str[] = {
3366  { LCP_RESERVED, "reserved" },
3367  { LCP_MRU, "MRU" },
3368  { LCP_ASYNCMAP, "AsyncMap" },
3369  { LCP_AUTHPROTO,"AUTH" },
3370  { LCP_QUALPROTO,"QUAL" },
3371  { LCP_MAGICNUM, "MAGIC" },
3372  { LCP_PCOMP, "PCOMP" },
3373  { LCP_ACFCOMP, "ACFcomp" },
3374  { LCP_CALLBACK, "CallBack" },
3375  { 0, NULL }
3376  };
3377 
3378 static const struct token ipcp_option2str[] = {
3379  { IPCP_RESERVED, "reserved" },
3380  { IPCP_ADDRS, "Addrs" },
3381  { IPCP_COMPRTYPE,"Compr" },
3382  { IPCP_ADDR, "Addr" },
3383  { IPCP_MS_DNS1, "DNS1" },
3384  { IPCP_MS_WINS1, "Wins1" },
3385  { IPCP_MS_DNS2, "DNS2" },
3386  { IPCP_MS_WINS2, "Win2" },
3387  { 0, NULL }
3388  };
3389 
3390 static const struct token lcpauth2str[] = {
3391  { 0xc023, "PAP" },
3392  { 0xc223, "CHAP" },
3393  { 0, NULL }
3394  };
3395 
3396 static const struct token lcpqual2str[] = {
3397  { 0xc025, "LQR" },
3398  { 0, NULL }
3399  };
3400 
3401 static const struct token lcpchap2str[] = {
3402  { 0x05, "MD5" },
3403  { 0x80, "MS" },
3404  { 0, NULL }
3405  };
3406 
3407 /*
3408  * Dump PPP-LCP contents. Functions taken from tcpdump.
3409  */
3410 static unsigned lcp_dump (const BYTE *bp)
3411 {
3412  WORD lcp_code, lcp_id, lcp_length, arg;
3413  const BYTE *lcp_data, *p;
3414  unsigned len = 0;
3415 
3416  lcp_code = bp[0];
3417  lcp_id = bp[1];
3418  lcp_length = intel16 (*(WORD*)(bp+2));
3419  lcp_data = bp + 4;
3420 
3421  len += dbug_printf ("LCP: %s id=0x%02x ",
3422  tok2str(ncp_code2str,"LCP-#%d",lcp_code), lcp_id);
3423 
3424  switch (lcp_code)
3425  {
3426  case CONFREQ:
3427  case CONFACK:
3428  case CONFNAK:
3429  case CONFREJ:
3430  p = lcp_data;
3431 
3432  while (p + 2 < lcp_data + lcp_length)
3433  {
3434  BYTE opt_type = p[0];
3435  BYTE opt_length = p[1];
3436 
3437  p += 2;
3438  dbug_printf ("<%s ", tok2str(lcp_option2str,"option-#%d",opt_type));
3439  if (opt_length)
3440  {
3441  switch (opt_type)
3442  {
3443  case LCP_MRU:
3444  arg = intel16 (*(WORD*)p);
3445  dbug_printf ("%u", arg);
3446  break;
3447 
3448  case LCP_AUTHPROTO:
3449  arg = intel16 (*(WORD*)p);
3450  dbug_printf (tok2str (lcpauth2str, "AUTH-%x", arg));
3451  if (opt_length >= 5)
3452  dbug_printf (" %s", tok2str(lcpchap2str, "%x", p[0]));
3453  break;
3454 
3455  case LCP_QUALPROTO:
3456  arg = intel16 (*(WORD*)p);
3457  dbug_printf (tok2str(lcpqual2str, "QUAL-%x", arg));
3458  break;
3459 
3460  case LCP_ASYNCMAP:
3461  case LCP_MAGICNUM:
3462  arg = intel16 (*(WORD*)(p+4));
3463  dbug_printf ("0x%08lX%04X", intel(*(DWORD*)p), arg);
3464  break;
3465 
3466  case LCP_PCOMP:
3467  case LCP_ACFCOMP:
3468  case LCP_RESERVED:
3469  break;
3470 
3471  default:
3472  break;
3473  }
3474  }
3475  dbug_putc ('>');
3476  p += opt_length - 2;
3477  }
3478  break;
3479 
3480  case ECHOREQ:
3481  case ECHOREP:
3482  case DISCARD:
3483  dbug_printf ("magic=0x%08lX", intel(*(DWORD*)lcp_data));
3484  lcp_data += 4;
3485  break;
3486 
3487  case PROTREJ:
3488  arg = intel16 (*(WORD*)lcp_data);
3489  dbug_printf ("prot=%s", tok2str(ppp_type2str, "PROT-%#x",arg));
3490  break;
3491 
3492  case CODEREJ:
3493  dbug_putc ('\n');
3494  lcp_dump (lcp_data);
3495  break;
3496 
3497  case TERMREQ:
3498  case TERMACK:
3499  break;
3500 
3501  default:
3502  break;
3503  }
3504  dbug_putc ('\n');
3505  return (len);
3506 }
3507 
3508 /*
3509  * Dump PPP-CCP contents (compression control protocol).
3510  */
3511 static unsigned ccp_dump (const BYTE *bp)
3512 {
3513  ARGSUSED (bp);
3514  return (0);
3515 }
3516 
3517 /*
3518  * Dump PPP-IPCP contents.
3519  */
3520 static unsigned ipcp_dump (const BYTE *bp)
3521 {
3522  WORD ipcp_code, ipcp_id, ipcp_length;
3523  const BYTE *ipcp_data, *p;
3524  unsigned len = 0;
3525 
3526  ipcp_code = bp[0];
3527  ipcp_id = bp[1];
3528  ipcp_length = intel16 (*(WORD*)(bp+2));
3529  ipcp_data = bp + 4;
3530 
3531  len += dbug_printf ("IPCP: %s id=0x%02x ",
3532  tok2str(ncp_code2str,"IPCP-#%d",ipcp_code), ipcp_id);
3533 
3534  switch (ipcp_code)
3535  {
3536  case CONFREQ:
3537  case CONFACK:
3538  case CONFNAK:
3539  case CONFREJ:
3540  p = ipcp_data;
3541 
3542  while (p + 2 < ipcp_data + ipcp_length)
3543  {
3544  BYTE opt_type = p[0];
3545  BYTE opt_length = p[1];
3546  DWORD addr;
3547 
3548  p += 2;
3549  dbug_printf ("<%s ", tok2str(ipcp_option2str,"option-#%d",opt_type));
3550  if (opt_length)
3551  {
3552  switch (opt_type)
3553  {
3554  case IPCP_ADDRS:
3555  addr = intel (*(DWORD*)p);
3556  dbug_printf ("addrs %s ", _inet_ntoa(NULL,addr));
3557  addr = intel (*(DWORD*)(p+4));
3558  dbug_printf ("%s", _inet_ntoa(NULL,addr));
3559  break;
3560 
3561  case IPCP_ADDR:
3562  addr = intel (*(DWORD*)p);
3563  dbug_printf ("addr %s", _inet_ntoa(NULL,addr));
3564  break;
3565 
3566  case IPCP_COMPRTYPE:
3567  dbug_printf ("compress %u", intel16(*(WORD*)p));
3568  break;
3569 
3570  case IPCP_MS_DNS1:
3571  case IPCP_MS_DNS2:
3572  addr = intel (*(DWORD*)p);
3573  dbug_printf ("MS-DNS %s", _inet_ntoa(NULL,addr));
3574  break;
3575 
3576  case IPCP_MS_WINS1:
3577  case IPCP_MS_WINS2:
3578  addr = intel (*(DWORD*)p);
3579  dbug_printf ("MS-WINS %s", _inet_ntoa(NULL,addr));
3580  break;
3581 
3582  default:
3583  break;
3584  }
3585  }
3586  dbug_putc ('>');
3587  p += opt_length - 2;
3588  }
3589  break;
3590 
3591  case TERMREQ:
3592  case TERMACK:
3593  break;
3594 
3595  default:
3596  break;
3597  }
3598  dbug_putc ('\n');
3599  return (len);
3600 }
3601 #endif /* USE_PPPOE */
3602 
3603 /*
3604  * Functions for writing dump-file in pcap-format
3605  * (gzip compressed or non-compressed pcap format).
3606  */
3607 #define TCPDUMP_MAGIC 0xA1B2C3D4
3608 #define PCAP_VERSION_MAJOR 2
3609 #define PCAP_VERSION_MINOR 4
3610 
3611 #include <sys/pack_on.h>
3612 
3614  DWORD magic;
3615  WORD version_major;
3616  WORD version_minor;
3617  DWORD thiszone; /* GMT to local correction */
3618  DWORD sigfigs; /* accuracy of timestamps */
3619  DWORD snap_len; /* max length saved portion of each pkt */
3620  DWORD linktype; /* data link type (DLT_*) */
3621  };
3622 
3623 /*
3624  * Each packet in the dump file is prepended with this generic header.
3625  * This gets around the problem of different headers for different
3626  * packet interfaces.
3627  */
3629  struct timeval ts; /* time stamp */
3630  DWORD caplen; /* length of portion present */
3631  DWORD len; /* length of this packet (off wire) */
3632  DWORD family; /* protocol family value (for DLT_NULL) */
3633  };
3634 
3635 #include <sys/pack_off.h>
3636 
3637 static int write_pcap_header (void)
3638 {
3639  struct pcap_file_header pf_hdr;
3640  struct timeval tv;
3641  struct timezone tz;
3642  size_t rc;
3643 
3644  gettimeofday2 (&tv, &tz);
3645  memset (&pf_hdr, 0, sizeof(pf_hdr));
3646 
3647  pf_hdr.magic = TCPDUMP_MAGIC;
3648  pf_hdr.version_major = PCAP_VERSION_MAJOR;
3649  pf_hdr.version_minor = PCAP_VERSION_MINOR;
3650  pf_hdr.thiszone = 60 * tz.tz_minuteswest;
3651  pf_hdr.sigfigs = 0;
3652  pf_hdr.snap_len = _mtu + _pkt_ip_ofs;
3653  pf_hdr.linktype = _pktserial ? 101 : _eth_get_hwtype(NULL, NULL);
3654 
3655 #if defined(USE_GZIP)
3656  if (use_gzip)
3657  {
3658  rc = gzwrite (dbg_file.gz_stream, &pf_hdr, sizeof(pf_hdr));
3659  bytes_raw += sizeof(pf_hdr);
3660  }
3661  else
3662 #endif
3663  rc = fwrite (&pf_hdr, 1, sizeof(pf_hdr), dbg_file.stream);
3664  return (rc == 0 ? -1 : (int)rc);
3665 }
3666 
3667 static int write_pcap_packet (const void *pkt, BOOL out)
3668 {
3669  const struct in_Header *ip = (const struct in_Header*) pkt;
3670  struct pcap_pkt_header pc_hdr;
3671  size_t hlen, pkt_len, rc;
3672 
3673  memset (&pc_hdr, 0, sizeof(pc_hdr));
3674 
3675  if (out)
3676  {
3677 #if (DOSX) && defined(HAVE_UINT64) && defined(__MSDOS__)
3678  if (!_eth_last.tx.tstamp.lo ||
3679  !get_tv_from_tsc (&_eth_last.tx.tstamp, &pc_hdr.ts))
3680 #endif
3681  gettimeofday2 (&pc_hdr.ts, NULL);
3682  pkt_len = _eth_last.tx.size;
3683  }
3684  else
3685  {
3686 #if (DOSX) && defined(HAVE_UINT64) && defined(__MSDOS__)
3687  if (!_eth_last.rx.tstamp.lo ||
3688  !get_tv_from_tsc (&_eth_last.rx.tstamp, &pc_hdr.ts))
3689 #endif
3690  gettimeofday2 (&pc_hdr.ts, NULL);
3691  pkt_len = _eth_last.rx.size;
3692  }
3693 
3694  if (_pktserial) /* write DLT_NULL header */
3695  {
3696  pc_hdr.len = (DWORD) (pkt_len + sizeof(pc_hdr.family));
3697  pc_hdr.family = (ip->ver == 4) ? AF_INET : AF_INET6;
3698  hlen = sizeof (pc_hdr);
3699  }
3700  else
3701  {
3702  pc_hdr.len = (DWORD)pkt_len;
3703  hlen = sizeof (pc_hdr) - sizeof(pc_hdr.family);
3704  }
3705  pc_hdr.caplen = (DWORD)pkt_len;
3706 
3707 #if defined(USE_GZIP)
3708  if (use_gzip)
3709  {
3710  rc = gzwrite (dbg_file.gz_stream, &pc_hdr, (unsigned)hlen);
3711  bytes_raw += (DWORD) hlen;
3712  rc = gzwrite (dbg_file.gz_stream, pkt, (unsigned)pkt_len);
3713  bytes_raw += (DWORD) pkt_len;
3714  }
3715  else
3716 #endif
3717  {
3718  fwrite (&pc_hdr, hlen, 1, dbg_file.stream);
3719  rc = fwrite (pkt, 1, pkt_len, dbg_file.stream);
3720  }
3721  return (rc == 0 ? -1 : (int)rc);
3722 }
3723 
3724 /*
3725  * This stuff is taken mostly from tests/cpu.c.
3726  */
3727 #if defined(PRINT_CPU_INFO)
3728 static const char *i486_model (int model)
3729 {
3730  static const char *models[] = {
3731  "0", "DX", "SX", "DX/2", "4", "SX/2", "6",
3732  "DX/2-WB", "DX/4", "DX/4-WB", "10", "11", "12", "13",
3733  "Am5x86-WT", "Am5x86-WB"
3734  };
3735  if (model < DIM(models))
3736  return (models[model]);
3737  return (NULL);
3738 }
3739 
3740 static const char *i586_model (int model)
3741 {
3742  static const char *models[] = {
3743  "0", "Pentium 60/66", "Pentium 75+", "OverDrive PODP5V83",
3744  "Pentium MMX", NULL, NULL, "Mobile Pentium 75+",
3745  "Mobile Pentium MMX"
3746  };
3747  if (model < DIM(models))
3748  return (models[model]);
3749  return (NULL);
3750 }
3751 
3752 static const char *Cx86_model (int type)
3753 {
3754  int model;
3755  static const char *models[] = {
3756  "unknown", "6x86", "6x86L", "6x86MX", "MII"
3757  };
3758  switch (type)
3759  {
3760  case 5:
3761  /* CX8 flag only on 6x86L */
3762  model = ((x86_capability & X86_CAPA_CX8) ? 2 : 1);
3763  break;
3764  case 6:
3765  model = 3;
3766  break;
3767  default:
3768  model = 0;
3769  }
3770  return (models[model]);
3771 }
3772 
3773 static const char *i686_model (int model)
3774 {
3775  static const char *models[] = {
3776  "PPro A-step", "Pentium Pro"
3777  };
3778  if (model < DIM(models))
3779  return (models[model]);
3780  return (NULL);
3781 }
3782 
3783 struct model_info {
3784  int type;
3785  const char *names[16];
3786  };
3787 
3788 static const char *AMD_model (int type, int model)
3789 {
3790  static const struct model_info amd_models[] = {
3791  { 4,
3792  { NULL, NULL, NULL, "DX/2", NULL, NULL, NULL, "DX/2-WB", "DX/4",
3793  "DX/4-WB", NULL, NULL, NULL, NULL, "Am5x86-WT", "Am5x86-WB"
3794  }
3795  },
3796  { 5,
3797  { "K5/SSA5 (PR-75, PR-90, PR-100)", "K5 (PR-120, PR-133)",
3798  "K5 (PR-166)", "K5 (PR-200)", NULL, NULL,
3799  "K6 (166-266)", "K6 (166-300)", "K6-2 (200-450)",
3800  "K6-3D-Plus (200-450)", NULL, NULL, NULL, NULL, NULL, NULL
3801  }
3802  }
3803  };
3804  int i;
3805 
3806  if (model < 16)
3807  for (i = 0; i < DIM(amd_models); i++)
3808  if (amd_models[i].type == type)
3809  return (amd_models[i].names[model]);
3810  return (NULL);
3811 }
3812 
3813 static const char *get_model (const char *vendor, int type, int model)
3814 {
3815  const char *p = NULL;
3816  static char buf[12];
3817 
3818  if (!x86_have_cpuid)
3819  return ("unknown");
3820 
3821  if (!strncmp(vendor, "Cyrix", 5))
3822  p = Cx86_model (type);
3823  else if (!strcmp(vendor, "AuthenticAMD"))
3824  p = AMD_model (type, model);
3825 #if 0
3826  else if (!strcmp(vendor, "UMC UMC UMC "))
3827  p = UMC_model (type, model);
3828  else if (!strcmp(vendor, "NexGenDriven"))
3829  p = NexGen_model (type, model);
3830  else if (!strcmp(vendor, "CentaurHauls"))
3831  p = Centaur_model (type, model);
3832  else if (!strcmp(vendor, "RiseRiseRise")) /* Rise Technology */
3833  p = Rise_model (type, model);
3834  else if (!strcmp(vendor, "GenuineTMx86")) /* Transmeta */
3835  p = Transmeta_model (type, model);
3836  else if (!strcmp(vendor, "Geode by NSC")) /* National Semiconductor */
3837  p = National_model (type, model);
3838 #endif
3839  else /* Intel */
3840  {
3841  switch (type & 0x07) /* mask off extended family bit */
3842  {
3843  case 4:
3844  p = i486_model (model);
3845  break;
3846  case 5:
3847  p = i586_model (model); /* Pentium I */
3848  break;
3849  case 6:
3850  p = i686_model (model); /* Pentium II */
3851  break;
3852  case 7:
3853  p = "Pentium 3";
3854  break;
3855  case 8:
3856  p = "Pentium 4";
3857  break;
3858  }
3859  }
3860  if (p)
3861  return (p);
3862  return itoa (model, buf, 10);
3863 }
3864 
3865 static void print_cpu_info (void)
3866 {
3867  CheckCpuType();
3868 
3869  dbug_printf ("CPU: %d86, model: %s, vendor: %s\n",
3870  x86_type, get_model(x86_vendor_id,x86_type,x86_model),
3871  x86_vendor_id[0] ? x86_vendor_id : "unknown");
3872 }
3873 #endif /* PRINT_CPU_INFO */
3874 #endif /* USE_DEBUG */
int W32_CALL parse_config_table(const struct config_table *tab, const char *section, const char *name, const char *value)
Parse the config-table and if a match is found for ('section'+'.
Definition: pcconfig.c:379
char _watt_assert_buf[256]
Definition: misc.c:62
BYTE karn_count
count of packets
Definition: wattcp.h:647
mac_address _eth_brdcast
Link-layer broadcast address.
Definition: pcsed.c:51
UINT rto
retransmission timeout
Definition: wattcp.h:646
convert to int
Definition: tcp.h:424
call convertion function
Definition: tcp.h:434
DWORD rtt_time
Round Trip Time value.
Definition: wattcp.h:651
DWORD vj_sd
VJ's alg, standard deviation (RTTVAR)
Definition: wattcp.h:644
static __inline BOOL match_ip6_dest(const in6_Header *ip)
Definition: pcdbug.c:388
BOOL _watt_is_init
watt_sock_init() done (but with possible failed boot)
Definition: sock_ini.c:157
BYTE W32_CALL _eth_get_hwtype(BYTE *hwtype, BYTE *hwlen)
Fill in hardware address type/length for BOOTP/DHCP packets.
Definition: pcsed.c:751
void W32_CALL _arp_debug_dump(void)
Debug-dump of configured gateways, route table and ARP cache.
Definition: pcarp.c:1907
BYTE cwindow
Congestion window.
Definition: wattcp.h:639
Definition: pcdbug.c:1463
static const char * dns_opcodes[16]
Debug of DNS (udp) records.
Definition: pcdbug.c:2954
int pkt_get_drvr_ver(WORD *major, WORD *minor, WORD *unused1, WORD *unused2)
Return version of PKTDRVR.
Definition: pcpkt.c:532
Another definition of 'struct DNS_head'.
Definition: pcdns.h:93
BYTE wwindow
Van Jacobson's algorithm.
Definition: wattcp.h:640
ip6_address his6addr
peer's IPv6 address
Definition: wattcp.h:620
volatile int _watt_cbroke
Definition: pc_cbrk.c:47
long send_una
unacked send data, must be signed
Definition: wattcp.h:625
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
Definition: ip_icmp.h:62
Definition: igmp.h:62
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
Definition: if_llc.h:54
mac_address _eth_addr
Local link-layer source address.
Definition: pcsed.c:50
DWORD vj_sa
VJ's alg, standard average (SRTT)
Definition: wattcp.h:643
Definition: route.h:56
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
DWORD W32_CALL set_timeout(DWORD msec)
Return time for when given timeout (msec) expires.
Definition: timer.c:503
static int icmp4_dump(const in_Header *ip)
Definition: pcdbug.c:877
static void dbug_exit(void)
Print ARP-cache and statistics counters to one of the debug-files.
Definition: pcdbug.c:2895
BYTE _eth_mac_len
Size of a MAC address.
Definition: pcsed.c:54
Definition: ip.h:67
char _pktdrvrname[20]
Name of PKDRVR.
Definition: pcpkt.c:62
Definition: wtime.h:38
WORD _pktdevclass
Ethernet, Token, FDDI etc.
Definition: pcpkt.c:51
BYTE unhappy
flag, indicates retransmitting segt's
Definition: wattcp.h:632
BOOL _rarp_on
Try booting using RARP ?
Definition: sock_ini.c:132
BOOL _pktserial
using serial driver, SLIP/PPP
Definition: pcpkt.c:54
BOOL _dhcp_on
Try booting using DHCP ?
Definition: sock_ini.c:130
Definition: zinftree.h:24
DWORD missed_seq[2]
S.
Definition: wattcp.h:665
struct pkt_info * _pkt_inf
module data that will be locked
Definition: pcpkt.c:64
long W32_CALL get_timediff(DWORD now, DWORD tim)
Return time difference between timers 'now' and 'tim'.
Definition: timer.c:621
DWORD my_ip_addr
our IP address
Definition: pctcp.c:70
BOOL _watt_fatal_error
Definition: misc.c:60
BOOL dbg_mode_all
These are public so they can be set by application if running without a config-file.
Definition: pcdbug.c:190
const char * _inet6_ntoa(const void *ip)
Convert an IPv6-address 'ip' into a string.
Definition: netaddr.c:401
WORD _ip6_checksum(const in6_Header *ip, WORD proto, const void *payload, unsigned payloadlen)
Generic IPv6 checksum function.
Definition: chksum.c:58
int _pkt_rxmode
active receive mode
Definition: pcpkt.c:56
BYTE tx_wscale
Definition: wattcp.h:675
struct _eth_last_info _eth_last
Sizes and timestamps of last packet recv/sent.
Definition: pcsed.c:68
int pkt_get_api_ver(WORD *ver)
Return version of spec.
Definition: pcpkt.c:519
Definition: wtime.h:47
static BOOL tcp_checksum(const in_Header *ip, const tcp_Header *tcp, int len)
Verify the TCP header checksum.
Definition: pctcp.c:2037
char *W32_CALL _inet_ntoa(char *s, DWORD ip)
Convert an IP-address 'ip' into a string.
Definition: netaddr.c:43
const char *W32_CALL wattcpVersion(void)
Return string for Watt-32 version.
Definition: version.c:76
DWORD last_seqnum[2]
increments
Definition: wattcp.h:629
DWORD last_acknum[2]
for pcdbug.c; to follow SEQ/ACK
Definition: wattcp.h:628
DWORD recv_next
SEQ number we expect to receive.
Definition: wattcp.h:623
WORD _pkt_ip_ofs
ofs from link-layer head to ip
Definition: pcpkt.c:52
DWORD send_next
SEQ we send but not ACK-ed by peer.
Definition: wattcp.h:624
BOOL _bootp_on
Try booting using BOOTP ?
Definition: sock_ini.c:129
UINT state
tcp connection state
Definition: wattcp.h:622
static BOOL udp_checksum(const in_Header *ip, const udp_Header *udp, int len)
Verify checksum for an UDP packet.
Definition: pctcp.c:848