Watt-32 tcp/ip  2.2 dev-rel.10
pctcp.c
Go to the documentation of this file.
1 
12 #include <stdio.h>
13 #include <stdarg.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <limits.h>
17 
18 #include "copyrigh.h"
19 #include "wattcp.h"
20 #include "chksum.h"
21 #include "strings.h"
22 #include "language.h"
23 #include "pcdns.h"
24 #include "bsdname.h"
25 #include "pcconfig.h"
26 #include "pcqueue.h"
27 #include "pcsed.h"
28 #include "pcstat.h"
29 #include "pcpkt.h"
30 #include "pcicmp.h"
31 #include "pcicmp6.h"
32 #include "pcigmp.h"
33 #include "pcdbug.h"
34 #include "pcdhcp.h"
35 #include "pcarp.h"
36 #include "pcbuf.h"
37 #include "netaddr.h"
38 #include "ip4_frag.h"
39 #include "ip4_in.h"
40 #include "ip4_out.h"
41 #include "misc.h"
42 #include "run.h"
43 #include "timer.h"
44 #include "rs232.h"
45 #include "split.h"
46 #include "pppoe.h"
47 #include "pctcp.h"
48 
49 #if defined(USE_BSD_API) || defined(USE_IPV6)
50 #include "socket.h"
51 #endif
52 
53 #ifndef __inline
54 #define __inline
55 #endif
56 
59 char hostname [MAX_HOSTLEN+1] = "random-pc";
60 
61 unsigned _mss = ETH_MAX_DATA - TCP_OVERHEAD;
62 unsigned _mtu = ETH_MAX_DATA;
63 BOOL mtu_discover = 0;
64 BOOL mtu_blackhole = 0;
65 BOOL block_tcp = 0;
66 BOOL block_udp = 0;
67 BOOL block_icmp = 0;
68 BOOL block_ip = 0;
70 DWORD my_ip_addr = 0L;
71 DWORD sin_mask = 0xFFFFFF00L;
75 #include <sys/pack_on.h>
76 
77 struct ip4_packet {
78  in_Header in;
79  udp_Header udp;
80  /* BYTE data[]; */
81  };
82 
83 struct ip6_packet {
84  in6_Header in;
85  udp_Header udp;
86  /* BYTE data[]; */
87  };
88 
89 struct tcp_pkt {
90  in_Header in;
91  tcp_Header tcp;
92  };
93 
94 struct tcp6_pkt {
95  in6_Header in;
96  tcp_Header tcp;
97  };
98 
99 #include <sys/pack_off.h>
100 
101 #if defined(USE_BSD_API)
102 
106  void *(MS_CDECL *_bsd_socket_hook) (enum BSD_SOCKET_OPS op, ...) = NULL;
107 #endif
108 
109 #if !defined(USE_UDP_ONLY)
110 
113  unsigned tcp_OPEN_TO = DEF_OPEN_TO;
114  unsigned tcp_CLOSE_TO = DEF_CLOSE_TO;
115  unsigned tcp_RTO_ADD = DEF_RTO_ADD;
116  unsigned tcp_RTO_BASE = DEF_RTO_BASE;
117  unsigned tcp_RTO_SCALE = DEF_RTO_SCALE;
118  unsigned tcp_RST_TIME = DEF_RST_TIME;
119  unsigned tcp_RETRAN_TIME = DEF_RETRAN_TIME;
120  unsigned tcp_MAX_VJSA = DEF_MAX_VJSA;
121  unsigned tcp_MAX_VJSD = DEF_MAX_VJSD;
125  BOOL tcp_opt_ts = FALSE;
126  BOOL tcp_opt_wscale = FALSE;
127  BOOL tcp_opt_sack = FALSE;
128 
131  BOOL tcp_nagle = TRUE;
132  unsigned tcp_keep_idle = 2*60;
133  unsigned tcp_keep_intvl = 30;
134  unsigned tcp_max_idle = 60;
135  DWORD tcp_recv_win = DEF_RECV_WIN;
139  extern int _tcp_fsm (_tcp_Socket **s, const in_Header *ip);
140 
141  static _tcp_Socket *tcp_findseq (const in_Header *ip, const tcp_Header *tcp);
142  static void tcp_sockreset (_tcp_Socket *s, BOOL proxy);
143 
144  static void tcp_no_arp (_tcp_Socket *s);
145  static void tcp_rtt_win (_tcp_Socket *s);
146  static void tcp_upd_win (_tcp_Socket *s, unsigned line);
147  static BOOL tcp_checksum (const in_Header *ip, const tcp_Header *tcp, int len);
148 #endif
149 
150 static void udp_close (const _udp_Socket *s);
151 
152 static void (W32_CALL *system_yield)(void) = NULL;
153 
157 int W32_CALL udp_listen (_udp_Socket *s, WORD lport, DWORD ip,
158  WORD port, ProtoHandler handler)
159 {
160  SIO_TRACE (("udp_listen"));
161 
162  udp_close (s);
163  WATT_LARGE_CHECK (s, sizeof(*s));
164  memset (s, 0, sizeof(*s));
165 
166  if (!_eth_is_init) /* GvB 2002-09, Lets us survive without a working eth */
167  {
168  SOCK_ERRNO (ENETDOWN);
169  s->err_msg = _LANG (_eth_not_init);
170  return (0);
171  }
172 
173  s->rx_data = &s->rx_buf[0];
174  s->max_rx_data = sizeof(s->rx_buf) - 1;
175  s->ip_type = UDP_PROTO;
176  s->sockmode = SOCK_MODE_BINARY | SOCK_MODE_UDPCHK;
177  s->myport = find_free_port (lport, 0); /* grab a local port */
178  s->hisport = port;
179  s->hisaddr = ip;
180  s->ttl = _default_ttl;
181  s->protoHandler = handler;
182  s->usr_yield = system_yield;
183  s->safetysig = SAFETY_UDP;
184  s->next = _udp_allsocs; /* insert into chain */
185  _udp_allsocs = s;
186  return (1);
187 }
188 
192 int W32_CALL udp_open (_udp_Socket *s, WORD lport, DWORD ip,
193  WORD port, ProtoHandler handler)
194 {
195  BOOL bcast;
196 
197  SIO_TRACE (("udp_open"));
198 
199  udp_close (s);
200  WATT_LARGE_CHECK (s, sizeof(*s));
201  memset (s, 0, sizeof(*s));
202 
203  if (!_eth_is_init) /* GvB 2002-09, Lets us survive without a working eth */
204  {
205  SOCK_ERRNO (ENETDOWN);
206  s->err_msg = _LANG (_eth_not_init);
207  return (0);
208  }
209 
210  if (ip && _ip4_is_multihome_addr(ip)) /* 0.0.0.0 is legal */
211  {
212  SOCK_ERRNO (EINVAL);
213  strcpy (s->err_buf, _LANG("Illegal destination "));
214  strcat (s->err_buf, _inet_ntoa(NULL,ip));
215  s->err_msg = s->err_buf;
216  return (0);
217  }
218 
219  bcast = ((ip == IP_BCAST_ADDR) || (~ip & ~sin_mask) == 0);
220 
221  if (bcast || !ip) /* check for broadcast */
222  {
223  memset (s->his_ethaddr, 0xFF, sizeof(eth_address));
224  if (!ip)
225  ip = IP_BCAST_ADDR; /* s->hisaddr = 255.255.255.255 (this network) */
226  }
227 #if defined(USE_MULTICAST)
228  else if (_ip4_is_multicast(ip)) /* check for multicast */
229  {
230  multi_to_eth (ip, &s->his_ethaddr);
231  s->ttl = 1; /* so we don't send worldwide as default */
232  }
233 #endif
234  else if (!_arp_resolve(ip,&s->his_ethaddr))
235  {
236  SOCK_ERRNO (EHOSTUNREACH);
237  strcpy (s->err_buf, _LANG("ARP failed "));
238  strcat (s->err_buf, _inet_ntoa(NULL,ip));
239  s->err_msg = s->err_buf;
240  STAT (ip4stats.ips_noroute++);
241  return (0);
242  }
243 
244  s->rx_data = &s->rx_buf[0];
245  s->max_rx_data = sizeof(s->rx_buf) - 1;
246  s->ip_type = UDP_PROTO;
247  s->sockmode = SOCK_MODE_BINARY | SOCK_MODE_UDPCHK;
248  s->myport = find_free_port (lport, 0);
249  s->myaddr = my_ip_addr;
250  s->ttl = _default_ttl;
251  s->hisaddr = ip;
252  s->hisport = port;
253  s->protoHandler = handler;
254  s->usr_yield = system_yield;
255  s->safetysig = SAFETY_UDP;
256  s->next = _udp_allsocs;
257  _udp_allsocs = s;
258  return (1);
259 }
260 
265 static void udp_close (const _udp_Socket *udp)
266 {
267  _udp_Socket *s, *prev;
268 
269  SIO_TRACE (("udp_close"));
270 
271  for (s = prev = _udp_allsocs; s; prev = s, s = s->next)
272  {
273  if (udp != s)
274  continue;
275 
276  reuse_localport (s->myport);
277 
278  if (s == _udp_allsocs)
279  _udp_allsocs = s->next;
280  else prev->next = s->next;
281  SET_ERR_MSG (s, _LANG("UDP Close called"));
282  break;
283  }
284 }
285 
289 int W32_CALL udp_SetTTL (_udp_Socket *s, BYTE ttl)
290 {
291  s->ttl = ttl;
292  return (0);
293 }
294 
295 
296 #if !defined(USE_UDP_ONLY)
297 
308 int W32_CALL tcp_open (_tcp_Socket *s, WORD lport, DWORD ip,
309  WORD rport, ProtoHandler handler)
310 {
311  SIO_TRACE (("tcp_open"));
312 
313  WATT_LARGE_CHECK (s, sizeof(*s));
314  _tcp_unthread (s, FALSE); /* just in case not totally closed */
315 
316  memset (s, 0, sizeof(*s));
317  s->state = tcp_StateCLOSED; /* otherwise is tcp_StateLISTEN on failure */
318 
319  STAT (tcpstats.tcps_connattempt++);
320 
321  if (!_eth_is_init) /* GvB 2002-09, Lets us survive without a working eth */
322  {
323  SOCK_ERRNO (ENETDOWN);
324  s->err_msg = _LANG (_eth_not_init);
325  return (0);
326  }
327 
328  if (!ip || _ip4_is_multihome_addr(ip) || _ip4_is_multicast(ip))
329  {
330  SOCK_ERRNO (EINVAL);
331  strcpy (s->err_buf, _LANG("Illegal destination "));
332  strcat (s->err_buf, _inet_ntoa(NULL,ip));
333  s->err_msg = s->err_buf;
334  return (0);
335  }
336 
337  if (!_arp_start_lookup(ip)) /* GvB 2002-09, now non-blocking */
338  {
339  SOCK_ERRNO (EHOSTUNREACH);
340  strcpy (s->err_buf, _LANG("Failed to start ARP lookup "));
341  strcat (s->err_buf, _inet_ntoa(NULL,ip));
342  s->err_msg = s->err_buf;
343  return (0);
344  }
345 
346  s->rx_data = &s->rx_buf[0];
347  s->max_rx_data = sizeof(s->rx_buf) - 1;
348  s->tx_data = &s->tx_buf[0];
349  s->max_tx_data = sizeof(s->tx_buf) - 1;
350  s->ip_type = TCP_PROTO;
351  s->max_seg = _mss;
352  s->state = tcp_StateRESOLVE;
353 
354  s->cwindow = 1;
355  s->wwindow = 0; /* slow start VJ algorithm */
356  s->vj_sa = INIT_VJSA;
357  s->rto = tcp_OPEN_TO; /* added 14-Dec 1999, GV */
358  s->myaddr = my_ip_addr;
359  s->myport = find_free_port (lport,1); /* get a nonzero port val */
360  s->locflags = LF_LINGER; /* close via TIMEWT state */
361  s->ttl = _default_ttl;
362  s->hisaddr = ip;
363  s->hisport = rport;
364  s->send_next = INIT_SEQ();
365  s->flags = tcp_FlagSYN;
366  s->unhappy = TRUE;
367  s->protoHandler = handler;
368  s->usr_yield = system_yield;
369 
370  s->safetysig = SAFETY_TCP; /* marker signatures */
371  s->safetytcp = SAFETY_TCP;
372  s->next = _tcp_allsocs; /* insert into chain */
373  _tcp_allsocs = s;
374 
377  if (tcp_nagle)
378  s->sockmode = SOCK_MODE_NAGLE;
379  s->sockmode |= SOCK_MODE_BINARY;
380 
381  return (1);
382 }
383 
389 int W32_CALL tcp_listen (_tcp_Socket *s, WORD lport, DWORD ip,
390  WORD port, ProtoHandler handler, WORD timeout)
391 {
392  SIO_TRACE (("tcp_listen"));
393 
394  WATT_LARGE_CHECK (s, sizeof(*s));
395  _tcp_unthread (s, FALSE); /* just in case not totally closed */
396  memset (s, 0, sizeof(*s));
397 
398  s->state = tcp_StateCLOSED; /* otherwise is tcp_StateLISTEN if success */
399 
400  if (!_eth_is_init) /* GvB 2002-09, Lets us survive without a working eth */
401  {
402  SOCK_ERRNO (ENETDOWN);
403  s->err_msg = _LANG (_eth_not_init);
404  return (0);
405  }
406 
407  if (_ip4_is_multicast(ip)) /* 0.0.0.0 is legal */
408  {
409  SOCK_ERRNO (EINVAL);
410  strcpy (s->err_buf, _LANG("Illegal destination "));
411  strcat (s->err_buf, _inet_ntoa(NULL,ip));
412  s->err_msg = s->err_buf;
413  return (0);
414  }
415 
416  s->rx_data = &s->rx_buf[0];
417  s->max_rx_data = sizeof(s->rx_buf) - 1;
418  s->tx_data = &s->tx_buf[0];
419  s->max_tx_data = sizeof(s->tx_buf) - 1;
420  s->ip_type = TCP_PROTO;
421  s->max_seg = _mss;
422  s->cwindow = 1;
423  s->wwindow = 0; /* slow start VJ algorithm */
424  s->vj_sa = INIT_VJSA;
425  s->state = tcp_StateLISTEN;
426  s->locflags = LF_LINGER | LF_IS_SERVER;
427  s->myport = find_free_port (lport, 0);
428  s->hisport = port;
429  s->hisaddr = ip;
430  s->send_next = INIT_SEQ();
431  s->unhappy = FALSE;
432  s->ttl = _default_ttl;
433  s->protoHandler = handler;
434  s->usr_yield = system_yield;
435  s->safetysig = SAFETY_TCP; /* marker signatures */
436  s->safetytcp = SAFETY_TCP;
437  s->next = _tcp_allsocs; /* insert into chain */
438  _tcp_allsocs = s;
439 
440  if (tcp_nagle)
441  s->sockmode = SOCK_MODE_NAGLE;
442  s->sockmode |= SOCK_MODE_BINARY;
443 
444  if (timeout != 0)
445  s->timeout = set_timeout (1000 * timeout);
446  return (1);
447 }
448 
456 {
457  SIO_TRACE (("_tcp_close"));
458 
459  if (s->ip_type != TCP_PROTO)
460  {
461  SIO_TRACE (("_tcp_close~0"));
462  return;
463  }
464 
465  if (s->state == tcp_StateESTAB ||
466  s->state == tcp_StateESTCL ||
467  s->state == tcp_StateSYNREC)
468  {
469  if (s->tx_datalen) /* must first flush all Tx data */
470  {
471  s->flags |= (tcp_FlagPUSH | tcp_FlagACK);
472  if (s->state < tcp_StateESTCL)
473  {
474  s->state = tcp_StateESTCL;
475  TCP_SENDSOON (s);
476  }
477  }
478  else /* really closing */
479  {
480  SET_ERR_MSG (s, _LANG("Connection closed normally"));
481  s->flags = (tcp_FlagACK | tcp_FlagFIN);
482  s->state = tcp_StateFINWT1;
483  s->timeout = set_timeout (tcp_TIMEOUT);
484  s->rtt_time = 0UL; /* stop RTT timer */
485  TCP_SEND (s);
486  }
487  s->unhappy = TRUE;
488  }
489  else if (s->state == tcp_StateCLOSWT)
490  {
491  /* need to ACK the FIN and get on with it
492  */
493  s->timeout = set_timeout (tcp_LASTACK_TIME); /* Added AGW 6 Jan 2001 */
494  s->state = tcp_StateLASTACK;
495  s->flags |= tcp_FlagFIN;
496  TCP_SEND (s);
497  s->unhappy = TRUE;
498  }
499  else if (s->state == tcp_StateRESOLVE || /* unlink failed connection */
500  s->state == tcp_StateSYNSENT)
501  {
502  s->state = tcp_StateCLOSED;
503  maybe_reuse_localport (s);
504  _tcp_unthread (s, FALSE);
505  }
506  SIO_TRACE (("_tcp_close~"));
507 }
508 
512 _tcp_Socket *_tcp_abort (_tcp_Socket *s, const char *file, unsigned line)
513 {
514  SIO_TRACE (("_tcp_abort"));
515 
516  SET_ERR_MSG (s, _LANG("TCP Abort"));
517 
518  TCP_TRACE_MSG (("_tcp_abort(%" ADDR_FMT ") called from %s (%u). State %s\n",
519  ADDR_CAST(s), file, line, tcpStateName(s->state)));
520 
521  if (s->state >= tcp_StateSYNSENT &&
522  s->state <= tcp_StateLASTACK)
523  {
524  s->flags = (tcp_FlagRST | tcp_FlagACK);
525  s->unhappy = TRUE;
526  if (s->state <= tcp_StateSYNREC)
527  {
528  s->rtt_time = 0UL; /* Stop RTT timer */
529  tcp_rtt_clr (s); /* Clear cached RTT */
530  }
531  s->tx_datalen = 0; /* RST should not carry any data */
532  TCP_SEND (s);
533  }
534  s->unhappy = FALSE;
535  s->ip_type = 0;
536  s->tx_datalen = 0; /* discard Tx buffer, but not Rx buffer */
537 
538  maybe_reuse_localport (s);
539  ARGSUSED (file);
540  ARGSUSED (line);
541  return _tcp_unthread (s, TRUE);
542 }
543 
555 int _tcp_sendsoon (_tcp_Socket *s, const char *file, unsigned line)
556 {
557  DWORD timeout;
558 
559  SIO_TRACE (("_tcp_sendsoon"));
560 
561  if (s->ip_type != TCP_PROTO)
562  return (0);
563 
564  if (s->state >= tcp_StateCLOSWT)
565  timeout = set_timeout (tcp_CLOSE_TO);
566  else timeout = set_timeout (tcp_RTO_BASE);
567 
568  if (s->rto <= tcp_RTO_BASE && s->recent == 0 &&
569  cmp_timers(s->rtt_time,timeout) <= 0)
570  { /* !! was == */
571  int rc;
572 
573  s->karn_count = 0;
574  rc = _tcp_send (s, file, line);
575  s->recent = 1;
576  return (rc);
577  }
578 
579  if ((s->unhappy || s->tx_datalen > 0 || s->karn_count == 1) &&
580  (s->rtt_time && cmp_timers(s->rtt_time,timeout) < 0))
581  return (0);
582 
583  if (s->state == tcp_StateSYNSENT) /* relaxed in SYNSENT state */
585  else s->rtt_time = set_timeout (s->rto / tcp_RTO_SCALE);
586 
587  s->karn_count = 1;
588 
589  return (0);
590 }
591 
597 {
598  _tcp_Socket *s, *prev;
599  _tcp_Socket *next = NULL;
600 
601  SIO_TRACE (("_tcp_unthread"));
602 
603  if (ds == NULL)
604  return (NULL);
605 
606  for (s = prev = _tcp_allsocs; s; prev = s, s = s->next)
607  {
608  if (ds != s)
609  continue;
610 
611  if (s == _tcp_allsocs)
612  _tcp_allsocs = s->next;
613  else prev->next = s->next;
614  next = s->next;
615  break;
616  }
617 
618  if (ds->rx_datalen == 0 || (ds->state > tcp_StateESTCL))
619  ds->ip_type = 0; /* fail further I/O */
620  ds->state = tcp_StateCLOSED; /* tcp_tick needs this */
621 
622  if (free_tx && ds->tx_data != NULL && ds->tx_data != &ds->tx_buf[0] &&
623  *(DWORD*)(ds->tx_data-4) == SAFETY_TCP)
624  {
625  free (ds->tx_data-4);
626  ds->tx_data = NULL;
627  ds->tx_datalen = 0; /* should already be 0 */
628  }
629  return (next);
630 }
631 
635 int W32_CALL tcp_established (const _tcp_Socket *s)
636 {
637  return (s->state >= tcp_StateESTAB);
638 }
639 
645 _tcp_Socket *_tcp_handler (const in_Header *ip, BOOL broadcast)
646 {
647 #if defined(USE_IPV6)
648  const in6_Header *ip6 = (const in6_Header*)ip;
649  ip6_address ip6_src, ip6_dst;
650 #endif
651 
652  tcp_Header *tcp;
653  _tcp_Socket *s;
654  int len;
655  BYTE flags;
656  DWORD source = intel (ip->source);
657  DWORD destin = intel (ip->destination);
658  DWORD seq;
659  WORD dstPort, srcPort;
660  BOOL is_ip4 = (ip->ver == 4);
661 
662  SIO_TRACE (("_tcp_handler"));
663 
664  if (is_ip4)
665  {
666  if (broadcast || block_tcp ||
667  !_ip4_is_local_addr(destin) || _ip4_is_multicast(source))
668  {
669  DEBUG_RX (NULL, ip);
670  return (NULL);
671  }
672 
673  len = in_GetHdrLen (ip); /* len of IP header */
674  tcp = (tcp_Header*) ((BYTE*)ip + len); /* tcp frame pointer */
675  len = intel16 (ip->length) - len; /* len of tcp+data */
676  flags = tcp->flags & tcp_FlagMASK; /* get TCP flags */
677 
678  if (!tcp_checksum(ip,tcp,len))
679  {
680  DEBUG_RX (NULL, ip);
681  return (NULL);
682  }
683  }
684 #if defined(USE_IPV6)
685  else
686  {
687  if (broadcast || block_tcp ||
688  !IN6_IS_ADDR_LINKLOCAL(&ip6->destination) ||
689  IN6_IS_ADDR_MULTICAST(&ip6->source))
690  {
691  DEBUG_RX (NULL, ip);
692  return (NULL);
693  }
694 
695  len = intel16 (ip6->len);
696  tcp = (tcp_Header*) pkt_get_type_in (TYPE_TCP_HEAD)->data;
697  flags = tcp->flags & tcp_FlagMASK;
698  memcpy (&ip6_dst, &ip6->destination, sizeof(ip6_dst));
699  memcpy (&ip6_src, &ip6->source, sizeof(ip6_src));
700  if (!_ip6_tcp_checksum(ip6,tcp,len))
701  {
702  DEBUG_RX (NULL, ip6);
703  return (NULL);
704  }
705  }
706 #else
707  else
708  {
709  DEBUG_RX (NULL, ip);
710  return (NULL);
711  }
712 #endif
713 
714 
715  dstPort = intel16 (tcp->dstPort);
716  srcPort = intel16 (tcp->srcPort);
717 
718  /* demux to active sockets
719  */
720  for (s = _tcp_allsocs; s; s = s->next)
721  {
722  if (s->safetysig != SAFETY_TCP || s->safetytcp != SAFETY_TCP)
723  {
724  outsnl (_LANG("Error in _tcp_handler()"));
725  DEBUG_RX (s, ip);
726  return (NULL);
727  }
728 
729  if (s->is_ip6 && !is_ip4)
730  {
731 #if defined(USE_IPV6)
732  if (s->hisport &&
733  !memcmp(&ip6_dst, &s->my6addr, sizeof(ip6_dst)) &&
734  !memcmp(&ip6_src, &s->his6addr, sizeof(ip6_src)) &&
735  dstPort == s->myport &&
736  srcPort == s->hisport)
737  break;
738 #endif
739  }
740  else if (is_ip4)
741  {
742  if (s->hisport && /* IP4: not a listening socket */
743  destin == s->myaddr && /* addressed to my IP */
744  source == s->hisaddr && /* and from my peer address */
745  dstPort == s->myport && /* addressed to my local port */
746  srcPort == s->hisport) /* and from correct remote port */
747  break;
748  }
749  }
750 
751  if (!s && (flags & tcp_FlagSYN))
752  {
753  /* demux to passive (listening) sockets, must be a new session
754  */
755  for (s = _tcp_allsocs; s; s = s->next)
756  if (s->hisport == 0 && /* =0, listening socket */
757  s->myport == dstPort) /* addressed to my local port */
758  {
759  if (s->is_ip6)
760  {
761 #if defined(USE_IPV6)
762  if (!is_ip4)
763  {
764  s->hisaddr = source;
765  s->hisport = srcPort;
766  memcpy (&s->my6addr, ip6_dst, sizeof(s->my6addr));
767  }
768 #endif
769  }
770  else if (is_ip4)
771  {
772  s->hisaddr = source; /* remember his IP-address */
773  s->hisport = srcPort; /* and src-port */
774  s->myaddr = destin; /* socket is now active (should be same) */
775  }
776  break;
777  }
778  }
779 
780  DEBUG_RX (s, ip);
781 
782  if (!s)
783  {
784  if (!(flags & tcp_FlagRST)) /* don't answer RST */
785  {
786  TCP_SEND_RESET (NULL, ip, tcp);
787  }
788  else if ((flags & tcp_FlagACK) && /* got ACK,RS */
789  (s = tcp_findseq(ip,tcp)) != NULL) /* ACK = SEQ + 1 */
790  {
791  /* e.g. a firewall is sending RST for host on inside.
792  */
793  tcp_sockreset (s, TRUE);
794  }
795  return (NULL);
796  }
797 
798 #if defined(USE_TCP_MD5)
799  if (is_ip4)
800  {
801  /* \todo: check in a src-host database and drop if not found
802  * and MD5 fails.
803  */
804  check_md5_signature (s, ip);
805  }
806 #endif
807 
808  /* Restart idle-timer unless overridden by tcp_connect().
809  */
810  if (sock_inactive && !(s->locflags & LF_RCVTIMEO))
811  s->inactive_to = set_timeout (1000 * sock_inactive);
812 
813  /* Got a RST with correct SEQ (RCV.NXT - RCV.NXT-RCV.RWIN+1).
814  * Reset socket (if socket is a server, go back to listening).
815  */
816  seq = intel (tcp->seqnum);
817  if ((flags & tcp_FlagRST) &&
818  SEQ_GEQ(seq, s->recv_next) &&
819  SEQ_LEQ(seq, s->recv_next+s->adv_win+1))
820  {
821  TCP_TRACE_MSG (("_tcp_handler(): got RST, SEQ %lu\n", seq));
822  tcp_sockreset (s, FALSE);
823  return (NULL);
824  }
825 
826  if (flags & tcp_FlagPUSH) /* EE 2002.2.28 */
827  s->locflags |= LF_GOT_PUSH;
828  else s->locflags &= ~LF_GOT_PUSH;
829 
830  tcp_rtt_win (s); /* update retrans timer, windows etc. */
831 
832  if (_tcp_fsm(&s,ip) && /* do input tcp state-machine */
833  s->unhappy) /* if "unhappy", retransmit soon */
834  TCP_SENDSOON (s);
835 
836 #if defined(USE_DEBUG)
837  _sock_check_tcp_buffers (s);
838 #endif
839 
840  return (s);
841 }
842 #endif /* !USE_UDP_ONLY */
843 
844 
848 static BOOL udp_checksum (const in_Header *ip, const udp_Header *udp, int len)
849 {
850  tcp_PseudoHeader ph = { 0,0,0,0,0,0 };
851 
852  ph.src = ip->source; /* already network order */
853  ph.dst = ip->destination;
854  ph.protocol = UDP_PROTO;
855  ph.length = udp->length;
856  ph.checksum = CHECKSUM (udp, len);
857 
858  if (CHECKSUM(&ph,sizeof(ph)) != 0xFFFF)
859  {
860  TCP_CONSOLE_MSG (1, (_LANG("Bad udp checksum. ")));
861  TCP_TRACE_MSG (("Bad udp checksum\n"));
862  STAT (udpstats.udps_badsum++);
863  return (FALSE);
864  }
865  return (TRUE);
866 }
867 
868 
873 static _udp_Socket *udp_demux (const in_Header *ip, BOOL ip_bcast,
874  DWORD destin, WORD srcPort, WORD dstPort,
875  BOOL *udp_err)
876 {
877  _udp_Socket *s;
878  BOOL is_ip4 = (ip->ver == 4);
879 
880 #if defined(USE_IPV6)
881  const in6_Header *ip6 = (const in6_Header*)ip;
882  ip6_address ip6_src, ip6_dst;
883 
884  if (!is_ip4)
885  {
886  memcpy (&ip6_dst, &ip6->destination, sizeof(ip6_dst));
887  memcpy (&ip6_src, &ip6->source, sizeof(ip6_src));
888  }
889 #endif
890 
891  *udp_err = FALSE; /* assume socket-list is OK */
892 
896  for (s = _udp_allsocs; s; s = s->next)
897  {
898  if (s->safetysig != SAFETY_UDP)
899  {
900  outsnl (_LANG("Error in udp_demux()"));
901  s->safetysig = SAFETY_UDP;
902  DEBUG_RX (s, ip);
903  *udp_err = TRUE;
904  return (NULL);
905  }
906 
907  if (!ip_bcast &&
908  (s->hisport != 0) &&
909  (dstPort == s->myport) &&
910  (srcPort == s->hisport))
911  {
912  if (s->is_ip6)
913  {
914 #if defined(USE_IPV6)
915  if (!is_ip4 &&
916  IN6_ARE_ADDR_EQUAL(&ip6_src,&s->his6addr)) /* !!mask */
917  {
918  DEBUG_RX (s, ip);
919  break;
920  }
921 #endif
922  }
923  else if (is_ip4 &&
924  ((destin & sin_mask) == (s->myaddr & sin_mask)) &&
925  (intel(ip->source) == s->hisaddr))
926  {
927  DEBUG_RX (s, ip);
928  break;
929  }
930  }
931  }
932 
933  if (!s)
934  {
935  /* demux to passive sockets
936  */
937  for (s = _udp_allsocs; s; s = s->next)
938  {
939  if (s->is_ip6)
940  {
941 #if defined(USE_IPV6)
942  if (!is_ip4 && dstPort == s->myport &&
943  IN6_IS_ADDR_UNSPECIFIED(&s->his6addr))
944  {
945  DEBUG_RX (s, ip);
946 
947  memcpy (&s->his6addr, &ip6_src, sizeof(s->his6addr));
948  s->hisport = srcPort;
949  SET_PEER_MAC_ADDR (s, ip6);
950  if (!ip_bcast)
951  memcpy (&s->my6addr, &ip6_dst, sizeof(s->my6addr));
952  break;
953  }
954 #endif
955  }
956  else if (is_ip4 && (s->hisaddr == 0 || s->hisaddr == IP_BCAST_ADDR) &&
957  dstPort == s->myport)
958  {
959  DEBUG_RX (s, ip);
960 
961  if (s->hisaddr == 0)
962  {
963  s->hisaddr = intel (ip->source); /* socket now active */
964  s->hisport = srcPort;
965  SET_PEER_MAC_ADDR (s, ip);
966 
967  /* take on value of expected destination
968  * unless it is broadcast
969  */
970  if (!ip_bcast)
971  s->myaddr = destin;
972  }
973  break;
974  }
975  }
976  }
977 
978 
979 #if defined(USE_MULTICAST)
980  if (is_ip4 && !s)
981  {
982  /* demux to multicast sockets
983  */
984  for (s = _udp_allsocs; s; s = s->next)
985  {
986  if (s->hisport != 0 &&
987  s->hisaddr == destin &&
988  dstPort == s->myport &&
989  _ip4_is_multicast(destin))
990  {
991  DEBUG_RX (s, ip);
992  break;
993  }
994  }
995  }
996 #endif
997 
998  if (!s)
999  {
1000  /* Demux to broadcast sockets.
1001  */
1002  for (s = _udp_allsocs; s; s = s->next)
1003  {
1004  if (s->is_ip6 && !is_ip4)
1005  {
1006 #if defined(USE_IPV6)
1007  if (dstPort == s->myport && IN6_IS_ADDR_UNSPECIFIED(&s->his6addr))
1008  {
1009  DEBUG_RX (s, ip);
1010  break;
1011  }
1012 #endif
1013  }
1014  else if (is_ip4)
1015  {
1016  if (s->hisaddr == IP_BCAST_ADDR && dstPort == s->myport)
1017  {
1018  DEBUG_RX (s, ip);
1019  break;
1020  }
1021  }
1022  }
1023  }
1024  return (s);
1025 }
1026 
1027 
1031 _udp_Socket *_udp_handler (const in_Header *ip, BOOL broadcast)
1032 {
1033 #if defined(USE_IPV6)
1034  const in6_Header *ip6 = (const in6_Header*)ip;
1035  ip6_address ip6_src, ip6_dst;
1036 #endif
1037 
1038  _udp_Socket *s;
1039  UINT len = 0;
1040  WORD dst_port, src_port;
1041  DWORD destin = 0;
1042  BOOL is_ip4 = (ip->ver == 4);
1043  BOOL ip_bcast = 0;
1044  BOOL udp_err;
1045 
1046  const BYTE *data;
1047  const udp_Header *udp = NULL;
1048 
1049  SIO_TRACE (("_udp_handler"));
1050 
1051  if (is_ip4)
1052  {
1053  destin = intel (ip->destination);
1054  ip_bcast = broadcast || /* link-layer broadcast */
1055  _ip4_is_ip_brdcast(ip); /* (directed) ip-broadcast */
1056  }
1057 #if defined(USE_IPV6)
1058  else
1059  {
1060  memcpy (&ip6_dst, &ip6->destination, sizeof(ip6_dst));
1061  memcpy (&ip6_src, &ip6->source, sizeof(ip6_src));
1062  ip_bcast = broadcast ||
1063  IN6_IS_ADDR_MULTICAST (&ip6->destination); /* !! */
1064  }
1065 #endif
1066 
1067 #if !defined(USE_MULTICAST)
1068 
1069  /* dst = ip number
1070  * or 255.255.255.255
1071  * or sin_mask.255.255
1072  * This is the only really gross hack in the multicasting stuff.
1073  * I'll fix it as soon as I can figure out what I want to do here.
1074  * -JRM 8/1/93
1075  */
1076  if (is_ip4 && !ip_bcast && /* not a IPv4 broadcast packet */
1077  my_ip_addr && /* and I know my address */
1078  !_ip4_is_multihome_addr(destin)) /* and not my address */
1079  {
1080  DEBUG_RX (NULL, ip);
1081  STAT (udpstats.udps_noport++);
1082  return (NULL);
1083  }
1084 #endif
1085 
1086  if (is_ip4)
1087  {
1088  len = in_GetHdrLen (ip);
1089  udp = (const udp_Header*) ((BYTE*)ip + len); /* udp segment pointer */
1090  len = intel16 (udp->length);
1091  }
1092 #if defined(USE_IPV6)
1093  else
1094  {
1095  len = intel16 (ip6->len);
1096  udp = (const udp_Header*) pkt_get_type_in (TYPE_UDP_HEAD)->data;
1097  len = intel16 (udp->length);
1098  }
1099 #endif
1100 
1101  if (len < sizeof(*udp))
1102  {
1103  DEBUG_RX (NULL, ip);
1104  STAT (udpstats.udps_hdrops++);
1105  return (NULL);
1106  }
1107 
1108  src_port = intel16 (udp->srcPort);
1109  dst_port = intel16 (udp->dstPort);
1110 
1111  if (dst_port == 0 || src_port == 0)
1112  {
1113  DEBUG_RX (NULL, ip);
1114  return (NULL);
1115  }
1116 
1117  s = udp_demux (ip, ip_bcast, destin, src_port, dst_port, &udp_err);
1118 
1119  if (!s) /* no demultiplexer found anything */
1120  {
1121  if (udp_err) /* error in udp_allsocs, don't send ICMP */
1122  return (NULL);
1123 
1124  DEBUG_RX (NULL, ip);
1125 
1126 #if defined(USE_IPV6)
1127  if (!is_ip4 && !IN6_IS_ADDR_UNSPECIFIED(&in6addr_my_ip) &&
1128  !memcmp(&in6addr_my_ip,&ip6_dst,sizeof(in6addr_my_ip)))
1129  {
1130  if (!ip_bcast && src_port != DOM_DST_PORT)
1131  icmp6_unreach (ip6, 3);
1132 
1133  if (ip_bcast)
1134  STAT (udpstats.udps_noportbcast++);
1135  else STAT (udpstats.udps_noport++);
1136  }
1137  else
1138 #endif
1139  if (is_ip4 && my_ip_addr && _ip4_is_multihome_addr(destin))
1140  {
1141  if (!ip_bcast && /* not broadcast */
1142  src_port != DOM_DST_PORT) /* not a late reply from a nameserver */
1143  icmp_send_unreach (ip, ICMP_UNREACH_PORT);
1144 
1145  if (ip_bcast)
1146  STAT (udpstats.udps_noportbcast++);
1147  else STAT (udpstats.udps_noport++);
1148  }
1149  return (NULL);
1150  }
1151 
1152  if (is_ip4)
1153  {
1154  if (udp->checksum && (s->sockmode & SOCK_MODE_UDPCHK) &&
1155  !udp_checksum (ip,udp,len))
1156  return (s);
1157  }
1158 #if defined(USE_IPV6)
1159  else
1160  {
1161  if (_ip6_udp_checksum(ip6,udp,len)) /* checksums are compulsary */
1162  return (s);
1163  }
1164 #endif
1165 
1166 
1167  /* Process user data. 0-byte probe is legal for s->protoHandler.
1168  */
1169  data = (const BYTE*) (udp+1);
1170  len -= sizeof(*udp);
1171 
1172  if (s->protoHandler)
1173  {
1174  if (is_ip4)
1175  {
1176  tcp_PseudoHeader ph = { 0,0,0,0,0,0 };
1177  ph.src = ip->source; /* only source needed by protoHandler */
1178  (*s->protoHandler) (s, data, len, &ph, udp);
1179  }
1180 #if defined(USE_IPV6)
1181  else
1182  {
1183  tcp_PseudoHeader6 ph6;
1184  memset (&ph6, 0, sizeof(ph6));
1185  memcpy (&ph6.src, &ip6->source, sizeof(ph6.src));
1186  (*s->protoHandler) (s, data, len, &ph6, udp);
1187  }
1188 #endif
1189  }
1190  else if (len > 0 /* && s->rx_datalen == 0 !! overwrite current data */)
1191  {
1192  if (len > s->max_rx_data) /* truncate data :-( */
1193  {
1194  len = s->max_rx_data;
1195  STAT (udpstats.udps_fullsock++);
1196  }
1197  memcpy (s->rx_data, data, len);
1198  s->rx_datalen = len;
1199  }
1200  return (s);
1201 }
1202 
1203 
1204 #if !defined(USE_UDP_ONLY)
1205 
1209 void tcp_Retransmitter (BOOL force)
1210 {
1211  _tcp_Socket *s, *next;
1212 
1213  static DWORD timeout = 0UL;
1214 
1215  SIO_TRACE (("tcp_Retransmitter"));
1216 
1217  /* do this once per tcp_RETRAN_TIME
1218  */
1219  if (!force && timeout && !chk_timeout(timeout))
1220  return;
1221 
1222  timeout = set_timeout (tcp_RETRAN_TIME);
1223 
1224  for (s = _tcp_allsocs; s; s = next)
1225  {
1226  next = s->next;
1227 
1228  /* Check on ARP resolve status, GvB 2002-09
1229  */
1230  if (s->state == tcp_StateRESOLVE)
1231  {
1232  if (_arp_lookup(s->hisaddr, &s->his_ethaddr)) /* Success */
1233  {
1234  UINT rtt, MTU;
1235 
1236  s->state = tcp_StateSYNSENT;
1237  s->timeout = set_timeout (tcp_LONGTIMEOUT);
1238  TCP_SEND (s); /* send opening SYN */
1239 
1240  /* find previous RTT replacing RTT set in tcp_send() above
1241  */
1242  if (tcp_rtt_get(s, &rtt, &MTU))
1243  s->rtt_time = set_timeout (rtt);
1244  else s->rtt_time = set_timeout (tcp_OPEN_TO);
1245  }
1246 
1247  /* If ARP no longer pending (timed out), hence we abort
1248  */
1249  else if (!_arp_lookup_pending(s->hisaddr)) /* ARP timed out */
1250  {
1251  tcp_no_arp (s);
1252  next = TCP_ABORT (s);
1253  }
1254  continue; /* don't do anything more on this TCB */
1255  }
1256 
1257  /* possible to be closed with Rx-data still queued
1258  */
1259  if (s->state == tcp_StateCLOSED)
1260  {
1261  if (s->rx_datalen == 0)
1262  {
1263  maybe_reuse_localport (s);
1264  next = _tcp_unthread (s, TRUE);
1265  }
1266  continue;
1267  }
1268 
1269  /* Need to send a window update? Because we advertised a 0 window
1270  * in a previous _tcp_send() (but only in ESTAB state).
1271  */
1272  if ((s->locflags & LF_WINUPDATE) && sock_rbleft((sock_type*)s) > 0)
1273  {
1274  STAT (tcpstats.tcps_sndwinup++);
1275  s->locflags &= ~LF_WINUPDATE;
1276  s->flags |= tcp_FlagACK;
1277  TCP_SEND (s);
1278  }
1279 
1280  else if (s->tx_datalen > 0 || s->unhappy || s->karn_count == 1)
1281  {
1282  if (chk_timeout(s->rtt_time)) /* retransmission timeout */
1283  {
1284  s->rtt_time = 0UL; /* stop RTT timer */
1285 
1286  TCP_CONSOLE_MSG (3, ("Regular retran TO set unacked back to "
1287  "0 from %ld\n", s->send_una));
1288 
1289  /* strategy handles closed windows. JD + EE
1290  */
1291  if (s->window == 0 && s->karn_count == 2)
1292  s->window = 1;
1293 
1294  if (s->karn_count == 0)
1295  {
1296  /* Simple "Slow start" algorithm:
1297  * Use the backed off RTO - implied, no code necessary.
1298  * Reduce the congestion window by 25%
1299  */
1300  unsigned cwindow = ((unsigned)(s->cwindow + 1) * 3) >> 2;
1301 
1302  s->cwindow = (BYTE) cwindow;
1303  if (s->cwindow == 0)
1304  s->cwindow = 1;
1305 
1306  s->wwindow = 0;
1307 #if 0
1308 
1309  s->send_ssthresh = s->cwindow * s->max_seg;
1310 #endif
1311  /* if really did timeout
1312  */
1313  s->karn_count = 2;
1314  s->send_una = 0;
1315  }
1316 
1317  if (s->tx_datalen > 0)
1318  {
1319  s->flags |= (tcp_FlagPUSH | tcp_FlagACK);
1320  if (s->cwindow > 1)
1321  s->cwindow--;
1322  }
1323 
1324  if (s->unhappy)
1325  STAT (tcpstats.tcps_rexmttimeo++); /* Normal re-xmit */
1326  else if (s->flags & tcp_FlagACK)
1327  STAT (tcpstats.tcps_delack++);
1328 
1329  TCP_SEND (s);
1330 
1331  if (s->state == tcp_StateSYNSENT)
1332  {
1335  TCP_TRACE_MSG (("SYN (re)sent in tcp_Retransmitter(), "
1336  " rtt_time %ld\n",
1338  }
1339  }
1340 
1341  /* handle inactive tcp timeouts (not sending data)
1342  */
1343  else if (chk_timeout(s->datatimer)) /* EE 99.08.23 */
1344  {
1345  next = TCP_ABORT (s);
1346  s->datatimer = 0UL;
1347  s->err_msg = _LANG ("Connection timed out - no data sent");
1348  }
1349  } /* end of retransmission strategy */
1350 
1351 
1352  /* handle inactive TCP timeouts (not received anything)
1353  */
1354  if (chk_timeout(s->inactive_to))
1355  {
1356  /* this baby has timed out. Don't do this again.
1357  */
1358  s->inactive_to = 0UL;
1359  s->err_msg = _LANG ("Timeout, nothing received");
1360  sock_close ((sock_type*)s);
1361  }
1362  else if (chk_timeout(s->timeout))
1363  {
1364  if (s->state == tcp_StateTIMEWT)
1365  {
1366  s->state = tcp_StateCLOSED;
1367  break;
1368  }
1369  if (s->state != tcp_StateESTAB && s->state != tcp_StateESTCL)
1370  {
1371  next = TCP_ABORT (s);
1372  s->err_msg = _LANG ("Timeout, aborting");
1373  break;
1374  }
1375  }
1376  }
1377 }
1378 #endif /* !USE_UDP_ONLY */
1379 
1380 
1389 WORD W32_CALL tcp_tick (sock_type *s)
1390 {
1391  static int tick_active = 0;
1392 
1393  if (tick_active > 0)
1394  {
1395  TCP_CONSOLE_MSG (1, ("tcp_tick() reentered\n"));
1396  return (s ? s->tcp.ip_type : 0);
1397  }
1398  tick_active++;
1399 
1400  SIO_TRACE (("tcp_tick"));
1401 
1402 #if !defined(USE_UDP_ONLY)
1403  /*
1404  * Finish off dead sockets
1405  */
1406  if (s)
1407  {
1408  if (s->tcp.ip_type == TCP_PROTO &&
1409  s->tcp.state == tcp_StateCLOSED &&
1410  s->tcp.rx_datalen == 0)
1411  {
1412  _tcp_unthread (&s->tcp, TRUE);
1413  s->tcp.ip_type = 0; /* fail further I/O */
1414  }
1415  }
1416 #endif
1417 
1423  while (tick_active == 1)
1424  {
1425  WORD eth_type = 0;
1426  BOOL brdcast = FALSE;
1427  void *packet = _eth_arrived (&eth_type, &brdcast);
1428 
1429  if (!packet) /* packet points to network layer protocol */
1430  break;
1431 
1432  switch (eth_type)
1433  {
1434  case IP4_TYPE:
1435  _ip4_handler ((in_Header*)packet, brdcast);
1436  break;
1437 
1438  case ARP_TYPE:
1439  _arp_handler ((arp_Header*)packet, brdcast);
1440  break;
1441 #if 0
1442  case RARP_TYPE:
1443  _rarp_handler ((rarp_Header*)packet, brdcast);
1444  break;
1445 #endif
1446 
1447 #if defined(USE_IPV6)
1448  case IP6_TYPE:
1449  _ip6_handler ((in6_Header*)packet, brdcast);
1450  break;
1451 #endif
1452 
1453 #if defined(USE_PPPOE)
1454  case PPPOE_DISC_TYPE:
1455  case PPPOE_SESS_TYPE:
1456  pppoe_handler ((pppoe_Packet*)packet);
1457  break;
1458 #endif
1459 
1460  default:
1461 #if defined(USE_DEBUG)
1462  dbug_printf ("\n%s (%d): Unhandled Rx packet, type %04X, "
1463  "broadcast %d\n", __FILE__, __LINE__,
1464  intel16(eth_type), brdcast);
1465 #endif
1466  break;
1467 
1468  /* RARP is only used during boot. Not needed here */
1469  }
1470  _eth_free (packet);
1471  }
1472 
1473 #if !defined(USE_UDP_ONLY)
1474  tcp_Retransmitter (FALSE); /* check for our outstanding packets */
1475 #endif
1476 
1477  daemon_run(); /* check and optionally run background processes */
1478 
1479  --tick_active;
1480  return (s ? s->tcp.ip_type : 0);
1481 }
1482 
1491 static int udp_write (_udp_Socket *s, const BYTE *data, int len)
1492 {
1493  struct ip4_packet *ip4_pkt = NULL;
1494 
1495 #if defined(USE_IPV6)
1496  struct ip6_packet *ip6_pkt = NULL;
1497  struct in6_Header *ip6 = NULL;
1498 #endif
1499 
1500  mac_address *dst = (_pktserial ? NULL : &s->his_ethaddr);
1501  in_Header *ip4 = NULL;
1502  udp_Header *udp;
1503 
1504  SIO_TRACE (("udp_write"));
1505 
1506 #if defined(USE_IPV6)
1507  if (s->is_ip6)
1508  {
1509  ip6_pkt = (struct ip6_packet*) _eth_formatpacket (dst, IP6_TYPE);
1510  ip6 = &ip6_pkt->in;
1511  udp = &ip6_pkt->udp;
1512  }
1513  else
1514 #endif
1515  {
1516  ip4_pkt = (struct ip4_packet*) _eth_formatpacket (dst, IP4_TYPE);
1517  ip4 = &ip4_pkt->in;
1518  udp = &ip4_pkt->udp;
1519  }
1520 
1521  /* build udp header
1522  */
1523  udp->srcPort = intel16 (s->myport);
1524  udp->dstPort = intel16 (s->hisport);
1525  udp->checksum = 0;
1526  udp->length = intel16 (sizeof(*udp)+len);
1527 
1528 #if defined(USE_IPV6)
1529  if (s->is_ip6)
1530  {
1531  memcpy (&ip6->source, &in6addr_my_ip, sizeof(ip6->source));
1532  memcpy (&ip6->destination, &s->his6addr, sizeof(ip6->destination));
1533  memcpy (ip6_pkt+1, data, len); /* copy 'data' to 'ip6_pkt->data[]' */
1534  udp->checksum = _ip6_checksum (ip6, IP6_NEXT_UDP, udp, sizeof(*udp)+len);
1535  if (!IP6_OUTPUT(ip6, &ip6->source, &ip6->destination, IP6_NEXT_UDP,
1536  sizeof(*udp)+len, 0, s))
1537  return (-1);
1538  return (len);
1539  }
1540  else
1541 #endif
1542  {
1543  tcp_PseudoHeader ph;
1544 
1545  memset (&ph, 0, sizeof(ph));
1546  ph.src = intel (s->myaddr);
1547  ph.dst = intel (s->hisaddr);
1548  if (len > 0)
1549  memcpy (ip4_pkt+1, data, len); /* copy 'data' to 'ip4_pkt->data[]' */
1550 
1551  if (s->sockmode & SOCK_MODE_UDPCHK)
1552  {
1553  ph.protocol = UDP_PROTO;
1554  ph.length = udp->length;
1555  ph.checksum = CHECKSUM (udp, sizeof(*udp)+len);
1556  udp->checksum = ~CHECKSUM (&ph, sizeof(ph));
1557  }
1558  if (!IP4_OUTPUT(ip4, ph.src, ph.dst, UDP_PROTO, s->ttl,
1559  (BYTE)_default_tos, 0, sizeof(*udp)+len, s))
1560  return (-1);
1561  return (len);
1562  }
1563 }
1564 
1571 static int udp_read (_udp_Socket *s, BYTE *buf, int maxlen)
1572 {
1573  int len = s->rx_datalen;
1574 
1575  SIO_TRACE (("udp_read"));
1576 
1577  if (maxlen < 0)
1578  maxlen = INT_MAX;
1579 
1580  if (len > maxlen)
1581  len = maxlen;
1582 
1583  if (len > 0)
1584  {
1585  if (buf)
1586  memcpy (buf, s->rx_data, len);
1587  s->rx_datalen -= len;
1588  if (s->rx_datalen > 0)
1589  memmove (s->rx_data, s->rx_data+len, s->rx_datalen);
1590  }
1591  return (len);
1592 }
1593 
1598 static void sock_reduce_mss (sock_type *s, WORD MTU)
1599 {
1600  if (s->tcp.ip_type == TCP_PROTO)
1601  {
1602 #if !defined(USE_UDP_ONLY)
1603  _tcp_Socket *tcp = &s->tcp;
1604 
1605  if (MTU)
1606  tcp->max_seg = _mtu - TCP_OVERHEAD;
1607  else if (tcp->max_seg > MSS_MIN)
1608  tcp->max_seg -= MSS_REDUCE;
1609  tcp->max_seg = min (max(MSS_MIN, tcp->max_seg), _mss);
1610 
1611  TCP_TRACE_MSG (("MSS for %s reduced to %u\n",
1612  _inet_ntoa(NULL,tcp->hisaddr), tcp->max_seg));
1613 #endif
1614  }
1615  else
1616  {
1617  /* doesn't use MSS yet (always MTU-28) */
1618  }
1619  ARGSUSED (MTU);
1620 }
1621 
1627 void _udp_cancel (const in_Header *ip, int icmp_type, int icmp_code,
1628  const char *msg, const void *arg) /* use a var-arg here ? */
1629 {
1630  WORD src_port, dst_port;
1631  BOOL passive = FALSE;
1632  int len = in_GetHdrLen (ip);
1633  udp_Header *udp = (udp_Header*) ((BYTE*)ip + len);
1634  _udp_Socket *s;
1635 
1636  SIO_TRACE (("_udp_cancel"));
1637 
1638  src_port = intel16 (udp->srcPort);
1639  dst_port = intel16 (udp->dstPort);
1640 
1641  for (s = _udp_allsocs; s; s = s->next) /* demux to active sockets */
1642  {
1643  if (s->hisport > 0 &&
1644  dst_port == s->hisport && src_port == s->myport &&
1645  intel(ip->destination) == s->hisaddr)
1646  break;
1647  }
1648 
1649  if (!s) /* check passive sockets */
1650  {
1651  passive = TRUE;
1652  for (s = _udp_allsocs; s; s = s->next)
1653  if (s->hisport == 0 && dst_port == s->myport)
1654  break;
1655  }
1656 
1657  if (s)
1658  {
1659  SET_ERR_MSG (s, msg);
1660 
1661  /* handle ICMP-errors on active sockets
1662  */
1663  if (icmp_type == ICMP_REDIRECT && !passive)
1664  {
1665  DWORD gateway;
1666 
1667  WATT_ASSERT (arg != NULL);
1668  gateway = *(DWORD*)arg;
1669  _ip_recursion = 1;
1670  _arp_resolve (gateway, &s->his_ethaddr);
1671  _ip_recursion = 0;
1672  }
1673  else if (icmp_type == ICMP_UNREACH && icmp_code == ICMP_UNREACH_NEEDFRAG && !passive)
1674  {
1675  WORD next_mtu;
1676 
1677  WATT_ASSERT (arg != NULL);
1678  next_mtu = *(WORD*) arg;
1679  sock_reduce_mss ((sock_type*)s, next_mtu);
1680  }
1681  else if (icmp_type != ICMP_TIMXCEED && !passive)
1682  {
1683  /* UDP isn't sturdy, close it on 1st ICMP error
1684  */
1685  SET_ERR_MSG (s, _LANG("Port unreachable"));
1686  s->ip_type = 0;
1687  s->locflags |= LF_GOT_ICMP;
1688  udp_close (s);
1689  }
1690  if (s->icmp_callb) /* tell the socket layer about it */
1691  (*s->icmp_callb) (s, icmp_type, icmp_code);
1692  }
1693  else
1694  {
1695  /* tell the INADDR_ANY sockets about it
1696  */
1697  for (s = _udp_allsocs; s; s = s->next)
1698  {
1699  if (s->icmp_callb)
1700  (*s->icmp_callb) (s, icmp_type, icmp_code);
1701  }
1702  }
1703 }
1704 
1705 #if !defined(USE_UDP_ONLY)
1706 /*
1707  * Default is to terminate socket on receiving 2nd
1708  * ICMP error. Use sock_sturdy() to change.
1709  */
1710 static BOOL tcp_stress_test (_tcp_Socket *s, const char *msg)
1711 {
1712  if (s->stress++ > s->rigid && s->rigid < 100) /* halt it */
1713  {
1714  SET_ERR_MSG (s, msg);
1715  s->rx_datalen = 0;
1716  s->tx_datalen = 0;
1717  s->unhappy = FALSE;
1718  s->locflags |= LF_GOT_ICMP;
1719  return (FALSE);
1720  }
1721  return (TRUE);
1722 }
1723 
1735 void _tcp_cancel (const in_Header *ip, int icmp_type, int icmp_code,
1736  const char *msg, const void *arg) /* use a var-arg here ? */
1737 {
1738  tcp_Header *tcp = (tcp_Header*) ((BYTE*)ip + in_GetHdrLen (ip));
1739  _tcp_Socket *s;
1740  DWORD gateway;
1741  WORD next_mtu;
1742  WORD src_port = intel16 (tcp->srcPort);
1743  WORD dst_port = intel16 (tcp->dstPort);
1744 
1745  SIO_TRACE (("_tcp_cancel"));
1746 
1747  /* demux to active sockets (passive cannot get ICMP)
1748  */
1749  for (s = _tcp_allsocs; s; s = s->next)
1750  {
1751  if (src_port != s->myport || dst_port != s->hisport ||
1752  intel(ip->destination) != s->hisaddr)
1753  continue;
1754 
1755  switch (icmp_type)
1756  {
1757  case ICMP_TIMXCEED:
1758  if (s->ttl < 255)
1759  s->ttl++;
1760  if (tcp_stress_test(s,msg))
1761  goto quench_it;
1762  TCP_ABORT (s);
1763  break;
1764 
1765  case ICMP_UNREACH:
1766  if (icmp_code == ICMP_UNREACH_NEEDFRAG)
1767  {
1768  WATT_ASSERT (arg != NULL);
1769  next_mtu = *(WORD*) arg;
1770 
1771  /* This should never happen since we normally don't send
1772  * with "Don't Fragment" set. As an optimisation we should
1773  * maybe reduce 'max_seg' for all sockets to this destination.
1774  */
1775  sock_reduce_mss ((sock_type*)s, next_mtu);
1776  break;
1777  }
1778  /* Other types are "fatal"
1779  */
1780  if (!tcp_stress_test(s,msg))
1781  {
1782  TCP_ABORT (s);
1783  break;
1784  }
1785  /* FALLTHROUGH */
1786 
1787  case ICMP_SOURCEQUENCH:
1788  quench_it:
1789  s->cwindow = 1; /* slow-down tx-rate */
1790  s->wwindow = 1;
1791  s->vj_sa <<= 2;
1792  s->vj_sd <<= 2;
1793  s->rto <<= 2;
1794  tcp_rtt_add (s, s->rto, _mtu);
1795  break;
1796 
1797  case ICMP_REDIRECT:
1798  /* don't bother handling redirect if we're closing
1799  */
1800  if (s->state < tcp_StateFINWT1)
1801  {
1802  WATT_ASSERT (arg != NULL);
1803  gateway = *(DWORD*)arg;
1804  SET_ERR_MSG (s, msg);
1805  _ip_recursion = 1;
1806  _arp_resolve (gateway, &s->his_ethaddr);
1807  _ip_recursion = 0;
1808  }
1809  break;
1810 
1811  case ICMP_PARAMPROB:
1812  SET_ERR_MSG (s, msg);
1813  TCP_ABORT (s);
1814  break;
1815  }
1816  if (s->icmp_callb)
1817  (*s->icmp_callb) (s, icmp_type, icmp_code); /* Notify BSD-socket */
1818 
1819  return; /* One ICMP message should only match one TCP socket */
1820  }
1821 }
1822 
1828 static int tcp_read (_tcp_Socket *s, BYTE *buf, int maxlen)
1829 {
1830  int len;
1831 
1832  SIO_TRACE (("tcp_read"));
1833 
1834  if (maxlen < 0)
1835  maxlen = INT_MAX;
1836 
1837  len = min (maxlen, s->rx_datalen);
1838 
1839  if (len > 0)
1840  {
1841  int to_move;
1842 
1843  if (buf)
1844  memcpy (buf, s->rx_data, len);
1845  s->rx_datalen -= len;
1846 
1847  to_move = s->rx_datalen;
1848  if (s->missed_seq[0] != s->missed_seq[1])
1849  to_move += s->missed_seq[1] - s->recv_next;
1850 
1851  if (to_move > 0)
1852  {
1853  memmove (s->rx_data, s->rx_data + len, to_move);
1854 
1855  TCP_SENDSOON (s); /* delayed ACK */
1856  }
1857  else
1858  tcp_upd_win (s, __LINE__);
1859  }
1860  else if (s->state == tcp_StateCLOSWT)
1861  _tcp_close (s);
1862 
1863  /* Added new EOF condition (GV, 11-Oct-2003)
1864  */
1865  if (len == 0 && (s->locflags & LF_GOT_FIN))
1866  return (-1);
1867  return (len);
1868 }
1869 
1876 static int tcp_write (_tcp_Socket *s, const BYTE *data, UINT len)
1877 {
1878  UINT room;
1879 
1880  SIO_TRACE (("tcp_write"));
1881 
1882  if (s->state != tcp_StateESTAB)
1883  return (0);
1884 
1885  room = s->max_tx_data - s->tx_datalen - 1;
1886  if (len > room)
1887  len = room;
1888  if (len > 0)
1889  {
1890  int rc = 0;
1891 
1892 #if defined(USE_DEBUG)
1893  _sock_check_tcp_buffers (s);
1894 #endif
1895 
1896  memcpy (s->tx_data + s->tx_datalen, data, len);
1897  s->tx_datalen += len;
1898 
1899  s->unhappy = TRUE; /* redundant because we have outstanding data */
1900  if (sock_data_timeout)
1901  s->datatimer = set_timeout (1000*sock_data_timeout); /* EE 99.08.23 */
1902  else s->datatimer = 0;
1903 
1904  if (s->sockmode & SOCK_MODE_LOCAL) /* queue up data, flush on next write */
1905  {
1906  s->sockmode &= ~SOCK_MODE_LOCAL;
1907  return (len);
1908  }
1909 
1910  if (!(s->sockmode & SOCK_MODE_NAGLE)) /* Nagle mode off */
1911  rc = TCP_SEND (s);
1912  else
1913  {
1914  /* Transmit if first segment or reached min (socket_MSS,MSS).
1915  */
1916  if (s->tx_datalen == len ||
1917  s->tx_datalen >= min(s->max_seg,_mss))
1918  rc = TCP_SEND (s);
1919  else rc = TCP_SENDSOON (s);
1920  }
1921  if (rc < 0)
1922  return (-1);
1923  }
1924  return (len);
1925 }
1926 
1927 
1933 static _tcp_Socket *tcp_findseq (const in_Header *ip, const tcp_Header *tcp)
1934 {
1935  _tcp_Socket *s;
1936  DWORD dst_host = intel (ip->destination);
1937  DWORD ack_num = intel (tcp->acknum);
1938  WORD dst_port = intel16 (tcp->dstPort);
1939 
1940  SIO_TRACE (("tcp_findseq"));
1941 
1942  for (s = _tcp_allsocs; s; s = s->next)
1943  {
1944  if (s->hisport != 0 &&
1945  dst_host == s->myaddr &&
1946  dst_port == s->myport &&
1947  ack_num == s->send_next+1)
1948  break;
1949  }
1950  return (s);
1951 }
1952 
1956 static void tcp_sockreset (_tcp_Socket *s, BOOL proxy)
1957 {
1958  const char *str = proxy ? "Proxy reset connection"
1959  : "Remote reset connection";
1960 
1961  SIO_TRACE (("tcp_sockreset"));
1962 
1963  if (debug_on)
1964  outsnl (_LANG(str));
1965 
1966  if (s->state == tcp_StateSYNREC)
1967  STAT (tcpstats.tcps_conndrops++); /* embryonic connection drop */
1968  else STAT (tcpstats.tcps_drops++);
1969 
1970  if (s->state != tcp_StateCLOSED && s->state != tcp_StateLASTACK)
1971  s->rx_datalen = 0;
1972 
1973  s->missed_seq[0] = s->missed_seq[1] = 0; /* discard buffered out-of-order */
1974 
1975  s->tx_datalen = 0; /* Empty Tx buffer */
1976 
1977  if (s->locflags & LF_IS_SERVER)
1978  {
1979  CLR_PEER_MAC_ADDR (s);
1980  s->cwindow = 1;
1981  s->rtt_time = 0UL;
1982  s->unhappy = FALSE;
1983  s->hisport = 0;
1984  s->hisaddr = 0UL;
1985  s->locflags &= ~(LF_WINUPDATE | LF_KEEPALIVE | LF_GOT_FIN | LF_GOT_ICMP);
1986 
1987  s->datatimer = 0UL;
1988  s->inactive_to = 0;
1989  s->timeout = 0;
1990  s->karn_count = 0;
1991  s->state = tcp_StateLISTEN;
1992  TCP_TRACE_MSG (("tcp_sockreset(): continue to LISTEN\n"));
1993  }
1994  else
1995  {
1996  s->err_msg = _LANG (str);
1997  s->state = tcp_StateCLOSED;
1998  s->ip_type = 0; /* 2001.1.18 - make it fail tcp_tick() */
1999 
2000 #if defined(USE_BSD_API)
2001  if (_bsd_socket_hook)
2002  (*_bsd_socket_hook) (BSO_RST_CALLBACK, s);
2003 #endif
2004  _tcp_unthread (s, TRUE);
2005  }
2006 }
2007 
2012 static void tcp_no_arp (_tcp_Socket *s)
2013 {
2014  SIO_TRACE (("tcp_no_arp"));
2015 
2016  s->err_msg = _LANG ("No ARP reply");
2017  STAT (ip4stats.ips_noroute++);
2018 
2019 #if defined(USE_BSD_API)
2020  if (_bsd_socket_hook)
2021  {
2022  Socket *sock = (Socket*) (*_bsd_socket_hook) (BSO_FIND_SOCK, s);
2023 
2024  if (sock) /* do a "read-wakeup" on the SOCK_STREAM socket */
2025  {
2026  sock->so_state |= SS_ISDISCONNECTING;
2027  sock->so_error = EHOSTUNREACH; /* !! Or ETIMEDOUT? */
2028  }
2029  }
2030 #endif
2031 }
2032 
2037 static BOOL tcp_checksum (const in_Header *ip, const tcp_Header *tcp, int len)
2038 {
2039  tcp_PseudoHeader ph = { 0,0,0,0,0,0 };
2040 
2041  SIO_TRACE (("tcp_checksum"));
2042 
2043  ph.src = ip->source;
2044  ph.dst = ip->destination;
2045  ph.protocol = TCP_PROTO;
2046  ph.length = intel16 (len);
2047  ph.checksum = CHECKSUM (tcp, len);
2048 
2049  if (CHECKSUM(&ph,sizeof(ph)) != 0xFFFF)
2050  {
2051  STAT (tcpstats.tcps_rcvbadsum++);
2052  TCP_CONSOLE_MSG (1, (_LANG("Bad tcp checksum. ")));
2053  TCP_TRACE_MSG (("Bad tcp checksum\n"));
2054  return (FALSE);
2055  }
2056  return (TRUE);
2057 }
2058 
2063 static void tcp_rtt_win (_tcp_Socket *s)
2064 {
2065  DWORD timeout;
2066 
2067  SIO_TRACE (("tcp_rtt_win"));
2068 
2069  /* update our retransmission stuff (Karn algorithm)
2070  */
2071  if (s->karn_count == 2) /* Wake up from slow-start */
2072  {
2073  TCP_CONSOLE_MSG (2, ("Finally got it safely zapped from %ld to ???\n",
2074  s->send_una));
2075  }
2076  else if (s->vj_last) /* We expect an immediate response */
2077  {
2078  long dT; /* Time (msec) since last (re)transmission */
2079  DWORD now;
2080 
2081  chk_timeout (0UL); /* Update date/date_ms */
2082  now = set_timeout (0);
2083 
2084 #if 0
2085  if (s->ts_echo && s->ts_echo >= s->ts_sent)
2086  dT = get_timediff (s->ts_echo, s->ts_sent) >> 1;
2087  else
2088 #else
2089  dT = get_timediff (now, s->vj_last);
2090 #endif
2091 
2092  if (dT >= 0)
2093  {
2094  dT -= (DWORD)(s->vj_sa >> 3);
2095  s->vj_sa += dT;
2096 
2097  if (dT < 0)
2098  dT = -dT;
2099 
2100  dT -= (s->vj_sd >> 2);
2101  s->vj_sd += dT; /* vj_sd = RTTVAR, rtt variance */
2102 
2103  if (s->vj_sa > tcp_MAX_VJSA) /* vj_sa = SRTT, smoothed RTT */
2104  s->vj_sa = tcp_MAX_VJSA;
2105  if (s->vj_sd > tcp_MAX_VJSD)
2106  s->vj_sd = tcp_MAX_VJSD;
2107  }
2108 
2109  /* only recompute RTT hence RTO after success
2110  */
2111  s->rto = tcp_RTO_BASE + (((s->vj_sa >> 2) + (s->vj_sd)) >> 1);
2112 
2113  tcp_rtt_add (s, s->rto, _mtu);
2114 
2115  TCP_CONSOLE_MSG (2, ("RTO %u sa %lu sd %lu cwindow %u"
2116  " wwindow %u unacked %ld\n",
2117  s->rto, s->vj_sa, s->vj_sd, s->cwindow,
2118  s->wwindow, s->send_una));
2119  }
2120 
2121  s->karn_count = 0;
2122  if (s->wwindow != 255)
2123  {
2126 #if 0
2127  if (s->cwindow * s->max_seg < s->send_ssthresh)
2128  s->cwindow++;
2129 #else
2130 
2131  /* A. Iljasov (iljasov@oduurl.ru) suggested this pre-increment
2132  */
2133  if (++s->wwindow >= s->cwindow)
2134  {
2135  if (s->cwindow != 255)
2136  s->cwindow++;
2137  s->wwindow = 0; /* mdurkin -- added 95.05.02 */
2138  }
2139 #endif
2140  }
2141 
2142  /* Restart RTT timer or postpone retransmission based on
2143  * calculated RTO. Make sure date/date_ms variables are updated
2144  * close to midnight.
2145  */
2146  chk_timeout (0UL);
2147  timeout = set_timeout (s->rto + tcp_RTO_ADD);
2148 
2149  if (s->rtt_time == 0UL || cmp_timers(s->rtt_time,timeout) < 0)
2150  s->rtt_time = timeout;
2151 
2152  s->datatimer = 0UL; /* resetting tx-timer, EE 99.08.23 */
2153 }
2154 
2158 static void tcp_upd_win (_tcp_Socket *s, unsigned line)
2159 {
2160  UINT winfree = s->max_rx_data - (UINT)s->rx_datalen;
2161 
2162  SIO_TRACE (("tcp_upd_win"));
2163 
2164  if (winfree < s->max_seg/2)
2165  {
2166  _tcp_send (s, __FILE__, line); /* update window now */
2167  TCP_CONSOLE_MSG (2, ("tcp_upd_win(%d): win-free %u\n", line, winfree));
2168  }
2169 }
2170 
2179 static __inline int tcp_opt_maxsegment (const _tcp_Socket *s, BYTE *opt)
2180 {
2181  *opt++ = TCPOPT_MAXSEG; /* option: MAXSEG,length,MSS */
2182  *opt++ = 4;
2183  *(WORD*) opt = intel16 ((WORD)s->max_seg);
2184  return (4);
2185 }
2186 
2192 static __inline int tcp_opt_timestamp (_tcp_Socket *s, BYTE *opt, DWORD ts_echo)
2193 {
2194  DWORD ts_now = set_timeout (0) - start_time; /* TSval */
2195  BYTE *start = opt;
2196 
2197  *opt++ = TCPOPT_NOP; /* NOP,NOP,TIMESTAMP,length,TSval,TSecho */
2198  *opt++ = TCPOPT_NOP; /* ---------- = 10 ------------- */
2199  *opt++ = TCPOPT_TIMESTAMP;
2200  *opt++ = 10;
2201  *(DWORD*) opt = intel (ts_now);
2202  opt += sizeof(ts_now);
2203  *(DWORD*) opt = intel (ts_echo);
2204  opt += sizeof(ts_echo);
2205  s->ts_sent = ts_now; /* remember TSval */
2206  return (opt - start); /* 20 bytes */
2207 }
2208 
2209 #if defined(USE_TCP_MD5)
2210 
2213 static BYTE *sign_opt;
2214 
2215 static __inline int tcp_opt_md5_sign (BYTE *opt)
2216 {
2217  *opt++ = TCPOPT_SIGNATURE; /* option: 19,length,MD5-signature,NOP,NOP */
2218  *opt++ = 2+TCPOPT_SIGN_LEN;
2219  sign_opt = opt; /* remember for finalise_md5_sign() */
2220  opt += TCPOPT_SIGN_LEN;
2221  *opt++ = TCPOPT_NOP;
2222  *opt++ = TCPOPT_NOP;
2223  return (4+TCPOPT_SIGN_LEN);
2224 }
2225 
2226 static __inline void finalise_md5_sign (const in_Header *ip,
2227  const tcp_Header *tcp,
2228  WORD tcp_len, const char *secret)
2229 {
2230  if (secret && sign_opt)
2231  make_md5_signature (ip, tcp, tcp_len, secret, sign_opt);
2232  sign_opt = NULL;
2233 }
2234 #endif
2235 
2236 
2237 #if defined(NOT_USED_YET)
2238 
2241 static __inline int tcp_opt_padding (BYTE *opt, int len)
2242 {
2243  int pad = len % 4;
2244 
2245  if (pad > 0)
2246  *opt++ = TCPOPT_NOP;
2247  if (pad > 1)
2248  *opt++ = TCPOPT_NOP;
2249  if (pad > 2)
2250  *opt++ = TCPOPT_NOP;
2251  if (pad > 3)
2252  *opt++ = TCPOPT_NOP;
2253  return (pad);
2254 }
2255 
2256 static __inline int tcp_opt_winscale (const _tcp_Socket *s, BYTE *opt)
2257 {
2258  *opt++ = TCPOPT_WINDOW; /* option: WINDOW,length,wscale */
2259  *opt++ = 3;
2260  *opt = s->tx_wscale;
2261  return (4);
2262 }
2263 
2264 static __inline int tcp_opt_sack_ok (const _tcp_Socket *s, BYTE *opt)
2265 {
2266  *opt++ = TCPOPT_SACKOK;
2267  *opt++ = 2;
2268  *opt++ = TCPOPT_NOP;
2269  *opt++ = TCPOPT_NOP;
2270  return (4);
2271 }
2272 
2273 static __inline int tcp_opt_sack (const _tcp_Socket *s, BYTE *opt,
2274  const struct SACK_list *sack)
2275 {
2276  int i, len = 2 + 8 * sack->num_blk;
2277 
2278  *opt++ = TCPOPT_SACK; /* option: SACK,length,left,right,.. */
2279  *opt++ = len;
2280  for (i = 0; i < sack->num_blk; i++)
2281  {
2282  *(DWORD*) opt = intel (sack->list[i].left_edge);
2283  opt += sizeof(DWORD);
2284  *(DWORD*) opt = intel (sack->list[i].right_edge);
2285  opt += sizeof(DWORD);
2286  }
2287  return (len + tcp_opt_padding(opt,len));
2288 }
2289 #endif /* NOT_USED_YET */
2290 
2291 
2295 static __inline int tcp_options (_tcp_Socket *s, BYTE *opt, BOOL is_syn)
2296 {
2297  int len = 0;
2298 
2299  if (s->locflags & LF_NOOPT) /* we suppress options */
2300  return (0);
2301 
2302  if (is_syn)
2303  {
2304  len = tcp_opt_maxsegment (s, opt);
2305 
2306  if (tcp_opt_ts)
2307  len += tcp_opt_timestamp (s, opt+len, 0UL);
2308 #if 0
2309  if (s->locflags & LF_REQ_SCALE)
2310  len += tcp_opt_winscale (s, opt+len);
2311  if (tcp_opt_sack)
2312  len += tcp_opt_sack_ok (s, opt+len);
2313 #endif
2314  }
2315  else if (tcp_opt_ts &&
2316  !(s->flags & (tcp_FlagFIN|tcp_FlagRST)) &&
2317  (s->locflags & LF_USE_TSTAMP))
2318  {
2319  /* We got a TS option in a previous SYN or SYN-ACK.
2320  * Echo it if "tcp.opt.ts = 1" and not sending a FIN/RST.
2321  */
2322  len = tcp_opt_timestamp (s, opt, s->ts_recent);
2323  s->locflags &= ~LF_USE_TSTAMP; /* don't echo this again */
2324  }
2325 
2326 #if defined(USE_TCP_MD5)
2327  if (s->secret)
2328  len += tcp_opt_md5_sign (opt+len);
2329 #endif
2330 
2331  WATT_ASSERT (len == 0 || (len % 4) == 0);
2332  return (len);
2333 }
2334 
2339 int _tcp_send (_tcp_Socket *s, const char *file, unsigned line)
2340 {
2341  struct tcp_pkt *pkt;
2342 
2343 #if defined(USE_IPV6)
2344  struct tcp6_pkt *pkt6;
2345  struct in6_Header *ip6 = NULL;
2346 #endif
2347 
2348  BOOL tx_ok;
2349  BYTE *data; /* where to copy user's data */
2350  mac_address *dst;
2351  in_Header *ip = NULL;
2352  tcp_Header *tcp;
2353  int send_tot_len = 0; /* count of data length we've sent */
2354  int send_data_len; /* how much data in this segment */
2355  int start_data; /* where data starts in tx-buffer */
2356  int send_tot_data; /* total amount of data to send */
2357  int tcp_len; /* total length of TCP segment */
2358  int opt_len; /* total length of TCP options */
2359  int pkt_num; /* 0 .. s->cwindow-1 */
2360  int rtt;
2361 
2362  SIO_TRACE (("_tcp_send"));
2363 
2364  s->recent = 0;
2365  dst = (_pktserial ? NULL : &s->his_ethaddr);
2366 
2367 #if defined(USE_IPV6)
2368  if (s->is_ip6)
2369  {
2370  pkt6 = (struct tcp6_pkt*) _eth_formatpacket (dst, IP6_TYPE);
2371  ip6 = &pkt6->in;
2372  tcp = &pkt6->tcp;
2373  }
2374  else
2375 #endif
2376  {
2377  pkt = (struct tcp_pkt*) _eth_formatpacket (dst, IP4_TYPE);
2378  ip = &pkt->in;
2379  tcp = &pkt->tcp;
2380  }
2381 
2382  data = (BYTE*) (tcp+1); /* data starts here if no options */
2383 
2384  if (s->karn_count == 2) /* doing slow-start */
2385  {
2386  send_tot_data = min (s->tx_datalen, s->window);
2387  start_data = 0;
2388  }
2389  else
2390  {
2391  /* Morten Terstrup <MorTer@dk-online.dk> found this signed bug
2392  */
2393  int size = min (s->tx_datalen, s->window);
2394 
2395  send_tot_data = size - s->send_una;
2396  if (send_tot_data < 0)
2397  send_tot_data = 0;
2398  start_data = s->send_una; /* relative tx_data[] */
2399  }
2400 
2401  /* step through our packets
2402  */
2403  for (pkt_num = 0; pkt_num < s->cwindow; pkt_num++)
2404  {
2405 #if 1
2406  if (s->safetysig != SAFETY_TCP || s->safetytcp != SAFETY_TCP)
2407  {
2408  outsnl (_LANG("Error in _tcp_send()"));
2409  s->safetysig = s->safetytcp = SAFETY_TCP;
2410  return (0);
2411  }
2412 #else
2413  WATT_ASSERT (s->safetysig == SAFETY_TCP); /* hard to find GoAhead bug! */
2414  WATT_ASSERT (s->safetytcp == SAFETY_TCP);
2415 #endif
2416 
2417  /* make tcp header
2418  */
2419  tcp->srcPort = intel16 (s->myport);
2420  tcp->dstPort = intel16 (s->hisport);
2421  tcp->seqnum = intel (s->send_next + start_data); /* unacked - no longer send_tot_len */
2422  tcp->acknum = intel (s->recv_next);
2423 
2424  s->adv_win = s->max_rx_data - s->rx_datalen; /* advertised recv window */
2425  tcp->window = intel16 ((WORD)s->adv_win);
2426  tcp->flags = (BYTE) s->flags;
2427  tcp->unused = 0;
2428  tcp->checksum = 0;
2429  tcp->urgent = 0;
2430 
2431  /* Insert any TCP options after header.
2432  */
2433  if (pkt_num == 0 && (s->flags & tcp_FlagSYN) == tcp_FlagSYN)
2434  {
2435  opt_len = tcp_options (s, data, TRUE);
2436  send_data_len = 0; /* no data, only options */
2437  }
2438  else
2439  {
2440  int data_free;
2441 
2442  opt_len = tcp_options (s, data, FALSE);
2443  data_free = s->max_seg - opt_len;
2444  if (data_free < 0)
2445  data_free = 0;
2446  send_data_len = min (send_tot_data, data_free);
2447  }
2448 
2449  tcp_len = sizeof(*tcp) + opt_len; /* TCP header length */
2450  data += opt_len;
2451  tcp->offset = tcp_len/4; /* # of 32-bit dwords */
2452 
2453  if (send_data_len > 0) /* non-SYN packets with data */
2454  {
2455  tcp_len += send_data_len;
2456  if (s->tx_queuelen)
2457  memcpy (data, s->tx_queue+start_data, send_data_len);
2458  else memcpy (data, s->tx_data +start_data, send_data_len);
2459  }
2460 
2461  if (s->locflags & LF_NOPUSH)
2462  tcp->flags &= ~tcp_FlagPUSH;
2463 
2464 #if defined(USE_TCP_MD5)
2465  finalise_md5_sign (ip, tcp, tcp_len-sizeof(*tcp), s->secret);
2466 #endif
2467 
2468  /* Send using _ip?_output()
2469  */
2470 #if defined(USE_IPV6)
2471  if (s->is_ip6)
2472  {
2473  memcpy (&ip6->source, &s->my6addr, sizeof(ip6->source));
2474  memcpy (&ip6->destination, &s->his6addr, sizeof(ip6->destination));
2475  tcp->checksum = _ip6_checksum (ip6, IP6_NEXT_TCP, tcp, tcp_len);
2476  tx_ok = _ip6_output (ip6, &ip6->source, &ip6->destination, IP6_NEXT_TCP,
2477  tcp_len, 0, s, file, line) != 0;
2478  }
2479  else
2480 #endif
2481  {
2482  tcp_PseudoHeader ph = { 0,0,0,0,0,0 };
2483 
2484  ph.src = intel (s->myaddr);
2485  ph.dst = intel (s->hisaddr);
2486  ph.protocol = TCP_PROTO;
2487  ph.length = intel16 (tcp_len);
2488  ph.checksum = CHECKSUM (tcp, tcp_len);
2489  tcp->checksum = ~CHECKSUM (&ph, sizeof(ph));
2490 
2491  tx_ok = _ip4_output (ip, ph.src, ph.dst, TCP_PROTO,
2492  s->ttl, s->tos, 0, tcp_len, s, file, line) != 0;
2493  }
2494 
2495  if (!tx_ok)
2496  {
2497  TCP_SENDSOON (s);
2498  return (-1);
2499  }
2500 
2501  /* do next packet
2502  */
2503  if (send_data_len > 0)
2504  {
2505  send_tot_len += send_data_len;
2506  start_data += send_data_len; /* new start of data */
2507  send_tot_data -= send_data_len; /* total data remaining */
2508  }
2509  if (send_tot_data <= 0)
2510  {
2511  pkt_num++;
2512  break;
2513  }
2514  }
2515 
2516  s->send_una = start_data; /* relative start of tx_data[] buffer */
2517 
2518  TCP_CONSOLE_MSG (2, ("tcp_send (called from %s/%u): sent %u bytes in %u "
2519  "packets with (%ld) unacked. SND.NXT %lu\n",
2520  file, line, send_tot_len, pkt_num, s->send_una,
2521  s->send_next));
2522 
2523  s->vj_last = 0UL;
2524  if (s->karn_count == 2)
2525  {
2526  if (s->rto)
2527  s->rto = (s->rto * 3) / 2; /* increase by 50% */
2528  else s->rto = 2*tcp_RTO_ADD; /* !!was 4 tick */
2529  }
2530  else
2531  {
2532  /* vj_last nonzero if we expect an immediate response
2533  */
2534  if (s->unhappy || s->tx_datalen)
2535  s->vj_last = set_timeout (0);
2536  s->karn_count = 0;
2537  }
2538 
2539  /* Determine when a retransmission should be sent
2540  */
2541  rtt = s->rto + tcp_RTO_ADD;
2542 
2543  s->rtt_time = set_timeout (rtt);
2544 
2545  if (send_tot_len > 0)
2546  s->rtt_lasttran = s->rtt_time;
2547 
2548  return (send_tot_len);
2549 }
2550 
2555 int _tcp_send_reset (_tcp_Socket *s, const in_Header *his_ip,
2556  const tcp_Header *org_tcp, const char *file, unsigned line)
2557 {
2558  tcp_PseudoHeader ph;
2559 
2560  #include <sys/pack_on.h>
2561 
2562  struct ip4_packet {
2563  in_Header ip;
2564  tcp_Header tcp;
2565  } *ip4_pkt = NULL;
2566 
2567 #if defined(USE_IPV6)
2568  struct ip6_packet {
2569  in6_Header ip;
2570  tcp_Header tcp;
2571  } *ip6_pkt = NULL;
2572 #endif
2573 
2574  #include <sys/pack_off.h>
2575 
2576  BYTE flags;
2577  tcp_Header *tcp;
2578  BOOL is_ip4 = (his_ip->ver == 4);
2579  DWORD acknum, seqnum;
2580  WORD tcp_len;
2581 
2582  if (tcp_RST_TIME) /* tcp_RST_TIME = 0: always send RST */
2583  {
2584  static DWORD next_RST_time = 0UL;
2585 
2586  if (next_RST_time && !chk_timeout(next_RST_time))
2587  return (-1);
2588 
2589  next_RST_time = set_timeout (tcp_RST_TIME);
2590  }
2591 
2592  flags = org_tcp->flags;
2593  if (flags == 0 || /* ignore if no flags set */
2594  (flags & tcp_FlagRST)) /* or RST set */
2595  return (-1);
2596 
2597  if ((flags & (tcp_FlagSYN|tcp_FlagACK)) == tcp_FlagSYN) /* SYN only */
2598  {
2599  acknum = intel (org_tcp->seqnum) + 1;
2600  seqnum = 0;
2601  flags = tcp_FlagACK;
2602  }
2603  else if (flags & tcp_FlagACK)
2604  {
2605  seqnum = intel (org_tcp->acknum);
2606  acknum = 0;
2607  flags = 0;
2608  }
2609  else
2610  {
2611  const in6_Header *his_ip6 = (const in6_Header*) his_ip;
2612  int len, ofs = org_tcp->offset << 2;
2613 
2614  if (is_ip4)
2615  len = intel16 (his_ip->length) - in_GetHdrLen (his_ip);
2616  else len = intel16 (his_ip6->len);
2617 
2618  acknum = intel (org_tcp->seqnum) + (len - ofs);
2619  seqnum = 0;
2620  flags = 0;
2621  }
2622 
2623 #if defined(USE_IPV6)
2624  if (!is_ip4)
2625  {
2626  ip6_pkt = (struct ip6_packet*) _eth_formatpacket (MAC_SRC(his_ip),
2627  IP6_TYPE);
2628  tcp = &ip6_pkt->tcp;
2629  }
2630  else
2631 #endif
2632  {
2633  ip4_pkt = (struct ip4_packet*) _eth_formatpacket (MAC_SRC(his_ip),
2634  IP4_TYPE);
2635  tcp = &ip4_pkt->tcp;
2636  }
2637 
2638  /* tcp header
2639  */
2640  tcp_len = sizeof(*tcp);
2641  tcp->srcPort = org_tcp->dstPort;
2642  tcp->dstPort = org_tcp->srcPort;
2643  tcp->seqnum = intel (seqnum);
2644  tcp->acknum = intel (acknum);
2645  tcp->window = 0; /* non-zero means "BSD derived" */
2646  tcp->flags = (flags & tcp_FlagMASK) | tcp_FlagRST;
2647  tcp->unused = 0;
2648  tcp->checksum = 0;
2649  tcp->urgent = 0;
2650 
2651 #if defined(USE_TCP_MD5)
2652  if (is_ip4 && s && s->secret)
2653  {
2654  tcp_len += tcp_opt_md5_sign ((BYTE*)(tcp+1));
2655  finalise_md5_sign (&ip4_pkt->ip, tcp, 0, s->secret);
2656  }
2657 #endif
2658 
2659  tcp->offset = tcp_len / 4;
2660 
2661 #if defined(USE_IPV6)
2662  if (!is_ip4)
2663  {
2664  in6_Header *ip6 = &ip6_pkt->ip;
2665 
2666  memcpy (&ip6->source, &in6addr_my_ip, sizeof(ip6->source));
2667  memcpy (&ip6->destination, ((in6_Header*)his_ip)->source, sizeof(ip6->destination));
2668  tcp->checksum = 0;
2669  tcp->checksum = _ip6_checksum (ip6, IP6_NEXT_TCP, tcp, tcp_len);
2670 
2671  return _ip6_output (ip6, &ip6->source, &ip6->destination,
2672  IP6_NEXT_TCP, tcp_len, 0, s, file, line);
2673  }
2674 #endif
2675 
2676  memset (&ph, 0, sizeof(ph));
2677  ph.src = his_ip->destination;
2678  ph.dst = his_ip->source;
2679  ph.protocol = TCP_PROTO;
2680  ph.length = intel16 (tcp_len);
2681  ph.checksum = CHECKSUM (tcp, tcp_len);
2682 
2683  tcp->checksum = ~CHECKSUM (&ph, sizeof(ph));
2684 
2685  return _ip4_output (&ip4_pkt->ip, ph.src, ph.dst, TCP_PROTO,
2686  s ? s->ttl : _default_ttl, his_ip->tos, 0,
2687  tcp_len, s, file, line);
2688 }
2689 
2699 {
2700  DWORD ack, seq;
2701  BYTE kc;
2702  int rc;
2703 
2704  SIO_TRACE (("_tcp_keepalive"));
2705 
2706  if (tcp->ip_type != TCP_PROTO || tcp->state < tcp_StateSYNSENT ||
2707  tcp->tx_datalen > 0)
2708  return (0);
2709 
2710  ack = tcp->recv_next;
2711  seq = tcp->send_next;
2712  kc = tcp->karn_count;
2713 
2714  tcp->recv_next = tcp->send_next;
2715  tcp->send_next = tcp->send_next + tcp->send_una - 1;
2716  tcp->flags = tcp_FlagACK;
2717  tcp->karn_count = 2;
2718  tcp->tx_datalen = 1; /* BSD 4.2 requires data to respond to a keepalive */
2719  tcp->tx_data[0] = '0';
2720  rc = TCP_SEND (tcp);
2721 
2722  tcp->tx_datalen = 0;
2723  tcp->recv_next = ack;
2724  tcp->send_next = seq;
2725  tcp->karn_count = kc;
2726  tcp->locflags &= ~LF_KEEPALIVE;
2727 
2728  STAT (tcpstats.tcps_keepprobe++);
2729  STAT (tcpstats.tcps_keeptimeo++);
2730  return (rc);
2731 }
2732 
2733 int W32_CALL sock_keepalive (sock_type *s)
2734 {
2735  return _tcp_keepalive (&s->tcp);
2736 }
2737 #endif /* !USE_UDP_ONLY */
2738 
2739 
2748 #define TCP_H_SM_BINARY 0x01
2749 #define TCP_H_SM_ASCII 0x02
2750 #define TCP_H_SM_UDP_MODE_CHK 0x04
2751 #define TCP_H_SM_UDP_MODE_NOCHK 0x08
2752 #define TCP_H_SM_TCP_MODE_NAGLE 0x10
2753 #define TCP_H_SM_TCP_MODE_NONAGLE 0x20
2754 #define TCP_H_SM_MASK 0x3F
2755 
2756 WORD W32_CALL sock_mode (sock_type *s, WORD mode)
2757 {
2758  if (s->tcp.ip_type == TCP_PROTO || s->tcp.ip_type == UDP_PROTO)
2759  {
2760  int old_nagle = (s->tcp.sockmode & SOCK_MODE_NAGLE);
2761  int old_bmode = (s->tcp.sockmode & SOCK_MODE_BINARY);
2762  int old_udpchk = (s->udp.sockmode &= SOCK_MODE_UDPCHK);
2763 
2764  mode &= TCP_H_SM_MASK;
2765  if (mode == 0)
2766  return (s->tcp.sockmode & SOCK_MODE_MASK);
2767 
2768  s->tcp.sockmode &= ~SOCK_MODE_MASK; /* turn all bits off */
2769 
2770  if (mode & TCP_H_SM_BINARY)
2771  s->tcp.sockmode |= SOCK_MODE_BINARY;
2772  else if (mode & TCP_H_SM_ASCII)
2773  s->tcp.sockmode &= ~SOCK_MODE_BINARY;
2774  else
2775  s->tcp.sockmode |= old_bmode;
2776 
2777  if (s->tcp.ip_type == UDP_PROTO)
2778  {
2779  if (mode & TCP_H_SM_UDP_MODE_CHK)
2780  s->udp.sockmode |= SOCK_MODE_UDPCHK;
2781  else if (mode & TCP_H_SM_UDP_MODE_NOCHK)
2782  s->udp.sockmode &= ~SOCK_MODE_UDPCHK;
2783  else
2784  s->udp.sockmode |= old_udpchk;
2785  return (s->udp.sockmode);
2786  }
2787 
2788  if (mode & TCP_H_SM_TCP_MODE_NAGLE)
2789  s->tcp.sockmode |= SOCK_MODE_NAGLE;
2790  else if (mode & TCP_H_SM_TCP_MODE_NONAGLE)
2791  s->tcp.sockmode &= ~SOCK_MODE_NAGLE;
2792  else
2793  s->tcp.sockmode |= old_nagle;
2794  return (s->tcp.sockmode);
2795  }
2796  return (0);
2797 }
2798 
2803 VoidProc W32_CALL sock_yield (_tcp_Socket *s, VoidProc func)
2804 {
2805  VoidProc old;
2806 
2807  if (s)
2808  {
2809  old = s->usr_yield;
2810  s->usr_yield = func;
2811  }
2812  else
2813  {
2814  old = system_yield;
2815  system_yield = func;
2816  }
2817  return (old);
2818 }
2819 
2823 int W32_CALL sock_abort (sock_type *s)
2824 {
2825  SIO_TRACE (("sock_abort"));
2826 
2827  switch (s->tcp.ip_type)
2828  {
2829 #if !defined(USE_UDP_ONLY)
2830  case TCP_PROTO:
2831  TCP_ABORT (&s->tcp);
2832  break;
2833 #endif
2834  case UDP_PROTO:
2835  udp_close (&s->udp);
2836  break;
2837  case IP4_TYPE:
2838  s->raw.ip_type = 0;
2839  s->raw.used = 0;
2840  break;
2841  }
2842  return (1);
2843 }
2844 
2845 #if defined(USE_BSD_API)
2846 
2849 static int raw_read (_raw_Socket *raw, BYTE *buf, int maxlen)
2850 {
2851  int len = 0;
2852 
2853  SIO_TRACE (("raw_read"));
2854 
2855  if (raw->used)
2856  {
2857  int hlen = in_GetHdrLen (&raw->ip);
2858  BYTE *data = (BYTE*)&raw->ip + hlen;
2859 
2860  len = intel16 (raw->ip.length) - hlen;
2861  len = min (len, maxlen);
2862  memcpy (buf, data, len);
2863  raw->used = 0;
2864  }
2865  return (len);
2866 }
2867 #endif
2868 
2875 int W32_CALL sock_read (sock_type *s, BYTE *buf, size_t maxlen)
2876 {
2877  int count = 0;
2878 
2879  SIO_TRACE (("sock_read"));
2880 
2881  do
2882  {
2883  int len = 0;
2884  int raw = 0;
2885 
2886  switch (s->udp.ip_type)
2887  {
2888 #if !defined(USE_UDP_ONLY)
2889  case TCP_PROTO:
2890  len = tcp_read (&s->tcp, buf, maxlen);
2891  break;
2892 #endif
2893  case UDP_PROTO:
2894  len = udp_read (&s->udp, buf, maxlen);
2895  break;
2896 
2897 #if defined(USE_BSD_API)
2898  case IP4_TYPE:
2899  raw = TRUE;
2900  len = raw_read (&s->raw, buf, maxlen);
2901  break;
2902 #endif
2903  }
2904 
2905  if (len < 1)
2906  {
2907  if (!tcp_tick(s) || len < 0)
2908  break;
2909  }
2910  else
2911  {
2912  count += len;
2913  buf += len;
2914  maxlen -= len;
2915  }
2916  if (maxlen > 0 && !raw)
2917  {
2918  if (s->tcp.usr_yield) /* yield only when room */
2919  (*s->tcp.usr_yield)(); /* 99.07.01 EE */
2920  else WATT_YIELD();
2921  }
2922  }
2923  while (maxlen);
2924  return (count);
2925 }
2926 
2931 int W32_CALL sock_fastread (sock_type *s, BYTE *buf, int len)
2932 {
2933  SIO_TRACE (("sock_fastread"));
2934 
2935  if (s->udp.ip_type == UDP_PROTO)
2936  return udp_read (&s->udp, buf, len);
2937 
2938 #if !defined(USE_UDP_ONLY)
2939  if (s->tcp.ip_type == TCP_PROTO || s->tcp.rx_datalen > 0)
2940  return tcp_read (&s->tcp, buf, len);
2941 #endif
2942 
2943 #if defined(USE_BSD_API)
2944  if (s->raw.ip_type == IP4_TYPE)
2945  return raw_read (&s->raw, buf, len);
2946 #endif
2947 
2948  return (-1);
2949 }
2950 
2951 
2960 int W32_CALL sock_write (sock_type *s, const BYTE *data, int len)
2961 {
2962  size_t chunk;
2963  size_t remain = len;
2964  int written = 0;
2965 
2966  SIO_TRACE (("sock_write"));
2967 
2968  while (remain > 0)
2969  {
2970  switch (s->udp.ip_type)
2971  {
2972 #if !defined(USE_UDP_ONLY)
2973  case TCP_PROTO:
2974  s->tcp.flags |= tcp_FlagPUSH;
2975  written = tcp_write (&s->tcp, data, remain);
2976  break;
2977 #endif
2978  case UDP_PROTO:
2979  chunk = min (_mtu - UDP_OVERHEAD, remain);
2980  written = udp_write (&s->udp, data, chunk);
2981  break;
2982 
2983 #if defined(USE_BSD_API)
2984  case IP4_TYPE:
2985  case IP6_TYPE:
2986  return (0); /* not supported yet */
2987 #endif
2988  default: /* EE 99.06.14 */
2989 #if defined(USE_DEBUG)
2990  dbug_printf ("sock_write() called with unknown proto %04Xh\n",
2991  s->udp.ip_type);
2992 #endif
2993  return (0);
2994  }
2995 
2996  if (written < 0)
2997  {
2998  s->udp.err_msg = _LANG ("Tx Error");
2999  return (0);
3000  }
3001  data += written;
3002  remain -= written;
3003 
3004  if (s->udp.usr_yield)
3005  (*s->udp.usr_yield)();
3006  else WATT_YIELD();
3007 
3008  if (!tcp_tick(s))
3009  return (0); /* !! should be 'len - remain' ? */
3010  }
3011  return (len);
3012 }
3013 
3018 int W32_CALL sock_fastwrite (sock_type *s, const BYTE *data, int len)
3019 {
3020  SIO_TRACE (("sock_fastwrite"));
3021 
3022  switch (s->udp.ip_type)
3023  {
3024  case UDP_PROTO:
3025  len = min ((int)(_mtu - UDP_OVERHEAD), len);
3026  len = udp_write (&s->udp, data, len);
3027  return (len < 0 ? 0 : len);
3028 
3029 #if !defined(USE_UDP_ONLY)
3030  case TCP_PROTO:
3031  len = tcp_write (&s->tcp, data, len);
3032  return (len < 0 ? 0 : len);
3033 #endif
3034  }
3035  return (0);
3036 }
3037 
3044 int W32_CALL sock_enqueue (sock_type *s, const BYTE *data, int len)
3045 {
3046  SIO_TRACE (("sock_enqueue"));
3047 
3048  if (len <= 0)
3049  return (0);
3050 
3051  if (s->udp.ip_type == UDP_PROTO)
3052  {
3053  int written = 0;
3054  int total = 0;
3055  do
3056  {
3057  len = min ((int)(_mtu - UDP_OVERHEAD), len);
3058  written = udp_write (&s->udp, data, len);
3059  if (written < 0)
3060  {
3061  s->udp.err_msg = _LANG ("Tx Error");
3062  break;
3063  }
3064  data += written;
3065  len -= written;
3066  total += written;
3067  }
3068  while (len > 0);
3069  return (total);
3070  }
3071 
3072 #if !defined(USE_UDP_ONLY)
3073  if (s->tcp.ip_type == TCP_PROTO)
3074  {
3075  s->tcp.tx_queue = data;
3076  s->tcp.tx_queuelen = len;
3077  s->tcp.tx_datalen = len;
3078  return TCP_SEND (&s->tcp);
3079  }
3080 #endif
3081  return (0);
3082 }
3083 
3084 #if !defined(USE_UDP_ONLY)
3085 
3088 void W32_CALL sock_noflush (sock_type *s)
3089 {
3090  SIO_TRACE (("sock_noflush"));
3091 
3092  if (s->tcp.ip_type == TCP_PROTO)
3093  {
3094  s->tcp.flags &= ~tcp_FlagPUSH;
3095  s->tcp.sockmode |= SOCK_MODE_LOCAL;
3096  }
3097 }
3098 
3103 void W32_CALL sock_flush (sock_type *s)
3104 {
3105  SIO_TRACE (("sock_flush"));
3106 
3107  if (s->tcp.ip_type == TCP_PROTO)
3108  {
3109  _tcp_Socket *tcp = &s->tcp;
3110 
3111  tcp->sockmode &= ~SOCK_MODE_LOCAL;
3112  if (tcp->tx_datalen > 0)
3113  {
3114  tcp->flags |= tcp_FlagPUSH;
3115  if (s->tcp.send_una == 0) /* !! S. Lawson - only if data not moving */
3116  TCP_SEND (tcp);
3117  }
3118  }
3119 }
3120 
3124 void W32_CALL sock_flushnext (sock_type *s)
3125 {
3126  SIO_TRACE (("sock_flushnext"));
3127 
3128  if (s->tcp.ip_type == TCP_PROTO)
3129  {
3130  s->tcp.flags |= tcp_FlagPUSH;
3131  s->tcp.sockmode &= ~SOCK_MODE_LOCAL;
3132  }
3133 }
3134 #endif /* !USE_UDP_ONLY */
3135 
3139 int W32_CALL sock_close (sock_type *s)
3140 {
3141  SIO_TRACE (("sock_close"));
3142 
3143  switch (s->tcp.ip_type)
3144  {
3145  case UDP_PROTO:
3146  udp_close (&s->udp);
3147  break;
3148 
3149 #if !defined(USE_UDP_ONLY)
3150  case TCP_PROTO:
3151  _tcp_close (&s->tcp);
3152  tcp_tick (s);
3153  break;
3154 #endif
3155  }
3156  return (0);
3157 }
3158 
3159 #if !defined(USE_UDP_ONLY)
3160 
3173 static struct tcp_rtt rtt_cache [RTTCACHE];
3174 
3175 void tcp_rtt_add (const _tcp_Socket *s, UINT rto, UINT MTU)
3176 {
3177  struct tcp_rtt *rtt;
3178  DWORD addr = s->hisaddr;
3179 
3180  SIO_TRACE (("tcp_rtt_add"));
3181 
3182  if (~addr & ~sin_mask) /* 0.0.0.0 or broadcast addresses? */
3183  return;
3184 
3185  rtt = &rtt_cache [(WORD)addr % RTTCACHE];
3186 
3187  /* Cache-slot is vacant or we're updating previous RTO
3188  * for same peer
3189  */
3190  if (!rtt->ip || rtt->ip == addr)
3191  {
3192  rtt->ip = addr;
3193  rtt->rto = rto;
3194  rtt->MTU = MTU;
3195  STAT (tcpstats.tcps_cachedrtt++);
3196  }
3197 }
3198 
3199 BOOL tcp_rtt_get (const _tcp_Socket *s, UINT *rto, UINT *MTU)
3200 {
3201  struct tcp_rtt *rtt = &rtt_cache [(s->hisaddr & 0xFFFF) % RTTCACHE];
3202 
3203  SIO_TRACE (("tcp_rtt_get"));
3204 
3205  STAT (tcpstats.tcps_segstimed++);
3206 
3207  if (s->hisaddr && rtt->ip == s->hisaddr && rtt->rto > 0)
3208  {
3209 #if defined(USE_DEBUG) && !defined(_MSC_VER) /* MSC6 crashes below */
3210  dbug_printf ("\nRTT-cache: host %s: %ss\n\n",
3211  _inet_ntoa(NULL, rtt->ip), time_str(rtt->rto));
3212 #endif
3213 
3214  STAT (tcpstats.tcps_usedrtt++);
3215  if (rto)
3216  *rto = rtt->rto;
3217  if (MTU)
3218  *MTU = rtt->MTU;
3219  return (TRUE);
3220  }
3221  return (FALSE);
3222 }
3223 
3224 void tcp_rtt_clr (const _tcp_Socket *s)
3225 {
3226  struct tcp_rtt *rtt = &rtt_cache [(s->hisaddr & 0xFFFF) % RTTCACHE];
3227 
3228  if (s->hisaddr && rtt->ip == s->hisaddr)
3229  {
3230  rtt->ip = 0;
3231  rtt->rto = 0;
3232  rtt->MTU = 0;
3233  }
3234 }
3235 #endif /* !USE_UDP_ONLY */
Definition: pctcp.c:94
int W32_CALL tcp_open(_tcp_Socket *s, WORD lport, DWORD ip, WORD rport, ProtoHandler handler)
Actively open a TCP connection.
Definition: pctcp.c:308
BYTE karn_count
count of packets
Definition: wattcp.h:647
BOOL W32_CALL _arp_handler(const arp_Header *ah, BOOL brdcast)
Receive ARP handler.
Definition: pcarp.c:1566
DWORD vj_last
last transmit time
Definition: wattcp.h:645
int W32_CALL sock_read(sock_type *s, BYTE *buf, size_t maxlen)
Read a socket with maximum 'maxlen' bytes.
Definition: pctcp.c:2875
int W32_CALL tcp_established(const _tcp_Socket *s)
Returns 1 if TCP connection is established.
Definition: pctcp.c:635
static __inline int tcp_options(_tcp_Socket *s, BYTE *opt, BOOL is_syn)
Append options to output TCP header.
Definition: pctcp.c:2295
UINT rto
retransmission timeout
Definition: wattcp.h:646
static void udp_close(const _udp_Socket *s)
Since UDP is stateless, simply reclaim the local-port and unthread the socket from the list...
Definition: pctcp.c:265
UINT MTU
Path-MTU discovered for this entry.
Definition: pctcp.h:173
BYTE tos
TOS from IP-header.
Definition: wattcp.h:648
void W32_CALL _eth_free(const void *pkt)
Free an input buffer once it is no longer needed.
Definition: pcsed.c:792
WORD flags
TCP flags used in next Tx.
Definition: wattcp.h:634
int W32_CALL udp_listen(_udp_Socket *s, WORD lport, DWORD ip, WORD port, ProtoHandler handler)
UDP passive open.
Definition: pctcp.c:157
int W32_CALL udp_open(_udp_Socket *s, WORD lport, DWORD ip, WORD port, ProtoHandler handler)
UDP active open.
Definition: pctcp.c:192
DWORD rtt_time
Round Trip Time value.
Definition: wattcp.h:651
DWORD inactive_to
inactive timer (no Rx data)
Definition: wattcp.h:671
int _default_ttl
Definition: ip4_out.c:54
DWORD vj_sd
VJ's alg, standard deviation (RTTVAR)
Definition: wattcp.h:644
_udp_Socket * _udp_handler(const in_Header *ip, BOOL broadcast)
Handler for incoming UDP packets.
Definition: pctcp.c:1031
void _tcp_close(_tcp_Socket *s)
Close a TCP connection.
Definition: pctcp.c:455
_tcp_Socket * _tcp_abort(_tcp_Socket *s, const char *file, unsigned line)
Abort a TCP connection.
Definition: pctcp.c:512
int _ip4_output(in_Header *ip, DWORD src_ip, DWORD dst_ip, BYTE protocol, BYTE ttl, BYTE tos, WORD ip_id, int data_len, const void *sock, const char *file, unsigned line)
The IP4 packet transmitter.
Definition: ip4_out.c:86
int W32_CALL sock_abort(sock_type *s)
Abort a UDP/TCP/Raw socket.
Definition: pctcp.c:2823
int _ip4_handler(const in_Header *ip, BOOL broadcast)
Definition: ip4_in.c:34
BYTE * tx_data
Tx data buffer (default tx_buf[])
Definition: wattcp.h:682
WORD ip_type
same ofs as for udp/tcp Socket
Definition: wattcp.h:695
Definition: socket.h:137
unsigned tcp_RTO_BASE
Base time for RTO calculation.
Definition: pctcp.c:116
int W32_CALL sock_close(sock_type *s)
Close a UDP/TCP socket.
Definition: pctcp.c:3139
int _tcp_keepalive(_tcp_Socket *tcp)
TCP keepalive transmission.
Definition: pctcp.c:2698
int W32_CALL sock_fastwrite(sock_type *s, const BYTE *data, int len)
Simpler, non-blocking (non-looping) version of sock_write().
Definition: pctcp.c:3018
static void tcp_upd_win(_tcp_Socket *s, unsigned line)
Check if receive window needs an update.
Definition: pctcp.c:2158
BYTE recent
1 if recently transmitted
Definition: wattcp.h:633
_udp_Socket * _udp_allsocs
list of udp-sockets
Definition: pctcp.c:73
BOOL block_tcp
when application handles TCP itself
Definition: pctcp.c:65
UINT rto
Round-trip timeout for this entry.
Definition: pctcp.h:172
BOOL used
used flag; packet not read yet
Definition: wattcp.h:696
DWORD ts_echo
last TimeStamp echo received
Definition: wattcp.h:656
BYTE cwindow
Congestion window.
Definition: wattcp.h:639
DWORD tcp_recv_win
RWIN for BSD sockets only.
Definition: pctcp.c:135
UINT max_tx_data
Last index for tx_data[].
Definition: wattcp.h:681
DWORD rtt_lasttran
RTT at last transmission.
Definition: wattcp.h:652
unsigned tcp_max_idle
max idle time before kill
Definition: pctcp.c:134
static __inline int tcp_opt_padding(BYTE *opt, int len)
Pad options to multiple of 4 bytes.
Definition: pctcp.c:2241
void W32_CALL sock_flush(sock_type *s)
Send pending TCP data.
Definition: pctcp.c:3103
BYTE rx_buf[udp_MaxBufSize+1]
received data buffer
Definition: wattcp.h:598
int _ip6_udp_checksum(const in6_Header *ip, const udp_Header *udp, unsigned len)
Check udp header checksum of an IPv6 packet.
Definition: chksum.c:105
BOOL mtu_blackhole
Definition: pctcp.c:64
BYTE wwindow
Van Jacobson's algorithm.
Definition: wattcp.h:640
ip6_address his6addr
peer's IPv6 address
Definition: wattcp.h:620
UINT tx_datalen
number of bytes of data to send
Definition: wattcp.h:680
BOOL block_icmp
when application handles ICMP itself
Definition: pctcp.c:67
DWORD ip
IP-address of this entry.
Definition: pctcp.h:171
long send_una
unacked send data, must be signed
Definition: wattcp.h:625
int _tcp_send(_tcp_Socket *s, const char *file, unsigned line)
Format and send an outgoing TCP segment.
Definition: pctcp.c:2339
ip6_address my6addr
my ip6-address
Definition: wattcp.h:601
Core definitions.
unsigned tcp_RTO_SCALE
Scaling used in RTO calculation.
Definition: pctcp.c:117
BYTE rx_buf[tcp_MaxBufSize+1]
received data buffer
Definition: wattcp.h:616
DWORD safetytcp
extra magic marker
Definition: wattcp.h:685
int W32_CALL tcp_listen(_tcp_Socket *s, WORD lport, DWORD ip, WORD port, ProtoHandler handler, WORD timeout)
Passively opens TCP a connection.
Definition: pctcp.c:389
int W32_CALL sock_write(sock_type *s, const BYTE *data, int len)
Writes data and returns length written.
Definition: pctcp.c:2960
static void tcp_sockreset(_tcp_Socket *s, BOOL proxy)
Resets a TCP connection.
Definition: pctcp.c:1956
static _tcp_Socket * tcp_findseq(const in_Header *ip, const tcp_Header *tcp)
Find the TCP socket that matches the tripplet: DESTADDR=MYADDR, DESTPORT=MYPORT and ACKNUM=SEQNUM+1 C...
Definition: pctcp.c:1933
DWORD vj_sa
VJ's alg, standard average (SRTT)
Definition: wattcp.h:643
BOOL _rarp_handler(const rarp_Header *rh, BOOL brdcast)
Handle incoming RARP packets.
Definition: pcrarp.c:52
int W32_CALL udp_SetTTL(_udp_Socket *s, BYTE ttl)
Set the TTL on an outgoing UDP datagram.
Definition: pctcp.c:289
ip6_address my6addr
our IPv6 address
Definition: wattcp.h:619
unsigned tcp_RTO_ADD
Time added in RTO calculation.
Definition: pctcp.c:115
VoidProc W32_CALL sock_yield(_tcp_Socket *s, VoidProc func)
Enable user defined yield function.
Definition: pctcp.c:2803
int _tcp_send_reset(_tcp_Socket *s, const in_Header *his_ip, const tcp_Header *org_tcp, const char *file, unsigned line)
Format and send a reset (RST) tcp packet.
Definition: pctcp.c:2555
DWORD W32_CALL set_timeout(DWORD msec)
Return time for when given timeout (msec) expires.
Definition: timer.c:503
DWORD ts_sent
last TimeStamp value sent
Definition: wattcp.h:654
BOOL _ip_recursion
avoid recursion in arp_resolve()
Definition: pcsed.c:56
static int tcp_read(_tcp_Socket *s, BYTE *buf, int maxlen)
Read from a TCP socket.
Definition: pctcp.c:1828
Definition: pctcp.h:170
static void sock_reduce_mss(sock_type *s, WORD MTU)
Reduce socket MSS upon receiving ICMP_UNREACH_NEEDFRAG.
Definition: pctcp.c:1598
DWORD sin_mask
our net-mask, 255.255.255.0
Definition: pctcp.c:71
void _tcp_cancel(const in_Header *ip, int icmp_type, int icmp_code, const char *msg, const void *arg)
Cancel a TCP socket.
Definition: pctcp.c:1735
char * secret
< linked-list of frags; not yet
Definition: wattcp.h:669
unsigned tcp_RST_TIME
Don't generate RST too often.
Definition: pctcp.c:118
static int tcp_write(_tcp_Socket *s, const BYTE *data, UINT len)
Write data to a TCP connection.
Definition: pctcp.c:1876
BYTE tx_buf[tcp_MaxTxBufSize+1]
data for transmission
Definition: wattcp.h:683
void *W32_CALL _eth_formatpacket(const void *mac_dest, WORD eth_type)
_eth_format_packet() places the next packet to be transmitted into the above link-layer output packet...
Definition: pcsed.c:135
BOOL W32_CALL _arp_lookup(DWORD ip, eth_address *eth)
Lookup MAC-address of 'ip'.
Definition: pcarp.c:1186
static BYTE * sign_opt
Prepare to insert MD5 option.
Definition: pctcp.c:2213
unsigned tcp_MAX_VJSA
Default max VJ std.
Definition: pctcp.c:120
Definition: ip.h:67
Definition: pctcp.c:89
int _ip6_output(in6_Header *ip, ip6_address *src_ip, ip6_address *dst_ip, BYTE protocol, unsigned data_len, int hop_lim, const void *sock, const char *file, unsigned line)
Definition: ip6_out.c:74
static _udp_Socket * udp_demux(const in_Header *ip, BOOL ip_bcast, DWORD destin, WORD srcPort, WORD dstPort, BOOL *udp_err)
Demultiplexer for incoming UDP packets.
Definition: pctcp.c:873
int W32_CALL sock_fastread(sock_type *s, BYTE *buf, int len)
Read a socket with maximum 'len' bytes.
Definition: pctcp.c:2931
DWORD safetysig
magic marker
Definition: wattcp.h:604
BYTE unhappy
flag, indicates retransmitting segt's
Definition: wattcp.h:632
_tcp_Socket * _tcp_unthread(_tcp_Socket *ds, BOOL free_tx)
Unthread a socket from the tcp socket list, if it's there.
Definition: pctcp.c:596
int pppoe_handler(const pppoe_Packet *pkt)
Handle incoming PPPoE packets.
Definition: pppoe.c:223
BOOL W32_CALL _arp_lookup_pending(DWORD ip)
An ARP-lookup timeout check.
Definition: pcarp.c:1206
DWORD safetysig
magic marker
Definition: wattcp.h:684
BOOL W32_CALL _arp_start_lookup(DWORD ip)
"PUBLIC" ARP/ROUTE FUNCTIONS.
Definition: pcarp.c:1169
BOOL _pktserial
using serial driver, SLIP/PPP
Definition: pcpkt.c:54
void tcp_Retransmitter(BOOL force)
Called periodically to perform retransmissions.
Definition: pctcp.c:1209
DWORD start_time
Start-time of watt_sock_init() (in msec)
Definition: timer.c:47
BOOL mtu_discover
Definition: pctcp.c:63
UINT window
other guy's window
Definition: wattcp.h:636
char hostname[MAX_HOSTLEN+1]
Our configured hostname.
Definition: pctcp.c:59
void *MS_CDECL * _bsd_socket_hook(enum BSD_SOCKET_OPS op,...)
This hook is to prevent the BSD-socket API being linked in by default.
int W32_CALL cmp_timers(DWORD t1, DWORD t2)
Compare two timers with expirary at 't1' and 't2'.
Definition: timer.c:359
BOOL tcp_opt_ts
TCP option config flags (RFC 1323).
Definition: pctcp.c:125
DWORD missed_seq[2]
S.
Definition: wattcp.h:665
UINT tx_queuelen
optional Tx queue length
Definition: wattcp.h:677
static int udp_read(_udp_Socket *s, BYTE *buf, int maxlen)
Read from UDP socket.
Definition: pctcp.c:1571
void W32_CALL sock_noflush(sock_type *s)
Sets non-flush mode on next TCP write.
Definition: pctcp.c:3088
int _tcp_sendsoon(_tcp_Socket *s, const char *file, unsigned line)
Schedule a transmission pretty soon.
Definition: pctcp.c:555
UINT adv_win
our last advertised window
Definition: wattcp.h:637
BOOL block_ip
when application handles IP itself
Definition: pctcp.c:68
BOOL block_udp
when application handles UDP itself
Definition: pctcp.c:66
int icmp_send_unreach(const in_Header *ip, int code)
Send an ICMP destination/protocol unreachable back to 'ip->source'.
Definition: pcicmp.c:194
BOOL _eth_is_init
we are initialised
Definition: pcsed.c:55
static __inline int tcp_opt_maxsegment(const _tcp_Socket *s, BYTE *opt)
TCP option routines.
Definition: pctcp.c:2179
BOOL tcp_nagle
Misc TCP values.
Definition: pctcp.c:131
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
static int raw_read(_raw_Socket *raw, BYTE *buf, int maxlen)
Read data from a raw-socket.
Definition: pctcp.c:2849
static __inline int tcp_opt_timestamp(_tcp_Socket *s, BYTE *opt, DWORD ts_echo)
Insert TimeStamp option.
Definition: pctcp.c:2192
DWORD datatimer
inactive timer (no Tx data)
Definition: wattcp.h:672
WORD _ip6_checksum(const in6_Header *ip, WORD proto, const void *payload, unsigned payloadlen)
Generic IPv6 checksum function.
Definition: chksum.c:58
static void tcp_rtt_win(_tcp_Socket *s)
Update retransmission timer, VJ algorithm and TCP windows.
Definition: pctcp.c:2063
WORD W32_CALL tcp_tick(sock_type *s)
Must be called periodically by user application (or BSD socket API).
Definition: pctcp.c:1389
_tcp_Socket * _tcp_handler(const in_Header *ip, BOOL broadcast)
The main TCP input handler.
Definition: pctcp.c:645
BOOL W32_CALL _arp_resolve(DWORD ip, eth_address *eth)
The blocking lookup function visible to higher functions.
Definition: pcarp.c:1279
BYTE tx_wscale
Definition: wattcp.h:675
void W32_CALL sock_flushnext(sock_type *s)
Causes next transmission to have a flush (PUSH bit set).
Definition: pctcp.c:3124
unsigned tcp_CLOSE_TO
Default close timeout.
Definition: pctcp.c:114
unsigned tcp_MAX_VJSD
Default max VJ std.
Definition: pctcp.c:121
UINT max_seg
MSS for this connection.
Definition: wattcp.h:658
unsigned tcp_keep_idle
idle time before sending keepalive
Definition: pctcp.c:132
unsigned tcp_RETRAN_TIME
Default retransmission time.
Definition: pctcp.c:119
_tcp_Socket * _tcp_allsocs
list of tcp-sockets
Definition: pctcp.c:137
static BOOL tcp_checksum(const in_Header *ip, const tcp_Header *tcp, int len)
Verify the TCP header checksum.
Definition: pctcp.c:2037
unsigned tcp_keep_intvl
time between keepalive probes
Definition: pctcp.c:133
char *W32_CALL _inet_ntoa(char *s, DWORD ip)
Convert an IP-address 'ip' into a string.
Definition: netaddr.c:43
int _ip6_tcp_checksum(const in6_Header *ip, const tcp_Header *tcp, unsigned len)
Check tcp header checksum of an IPv6 packet.
Definition: chksum.c:90
static void tcp_no_arp(_tcp_Socket *s)
Called for a TCP socket when ARP lookup fails.
Definition: pctcp.c:2012
ip6_address his6addr
peer's ip-6 address
Definition: wattcp.h:602
void _udp_cancel(const in_Header *ip, int icmp_type, int icmp_code, const char *msg, const void *arg)
Cancel an UDP socket.
Definition: pctcp.c:1627
BOOL W32_CALL chk_timeout(DWORD value)
Check if milli-sec value has expired:
Definition: timer.c:547
void *W32_CALL _eth_arrived(WORD *type_ptr, BOOL *broadcast)
Poll for arrival of new packets (IP/ARP/RARP/PPPoE protocol).
Definition: pcsed.c:1026
DWORD recv_next
SEQ number we expect to receive.
Definition: wattcp.h:623
static struct tcp_rtt rtt_cache[RTTCACHE]
Round-trip timing cache routines.
Definition: pctcp.c:3173
int W32_CALL sock_enqueue(sock_type *s, const BYTE *data, int len)
For UDP, this function is same as sock_write().
Definition: pctcp.c:3044
DWORD ts_recent
last TimeStamp value received
Definition: wattcp.h:655
DWORD send_next
SEQ we send but not ACK-ed by peer.
Definition: wattcp.h:624
BYTE _default_tos
Definition: ip4_out.c:53
unsigned tcp_OPEN_TO
TCP timer values.
Definition: pctcp.c:113
DWORD timeout
timer for retrans etc.
Definition: wattcp.h:631
static int udp_write(_udp_Socket *s, const BYTE *data, int len)
Write an UDP packet.
Definition: pctcp.c:1491
struct tcp_Socket * next
link to next tcp-socket
Definition: wattcp.h:613
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