Watt-32 tcp/ip  2.2 dev-rel.10
socket.c
Go to the documentation of this file.
1 
5 /* BSD sockets functionality for Watt-32 TCP/IP.
6  *
7  * Copyright (c) 1997-2002 Gisle Vanem <gvanem@yahoo.no>
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  * must display the following acknowledgement:
19  * This product includes software developed by Gisle Vanem
20  * Bergen, Norway.
21  *
22  * THIS SOFTWARE IS PROVIDED BY ME (Gisle Vanem) AND CONTRIBUTORS ``AS IS''
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL I OR CONTRIBUTORS BE LIABLE FOR ANY
26  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Version
34  *
35  * 0.5 : Dec 18, 1997 : G. Vanem - created
36  * 0.6 : Aug 06, 2002 : G. Vanem - added AF_INET6 support
37  */
38 
39 #include "socket.h"
40 #include "pcdbug.h"
41 #include "pcicmp6.h"
42 #include "pcdns.h"
43 
44 #if defined(USE_BSD_API)
45 
46 #if defined(__DJGPP__)
47  #include <sys/resource.h>
48  #include <sys/fsext.h>
49  #include <unistd.h>
50  #if (DJGPP_MINOR >= 4)
51  #include <libc/fd_props.h>
52  #endif
53 
54  /* in fsext.c */
55  extern int _fsext_demux (__FSEXT_Fnumber func, int *rv, va_list _args);
56 
57 #elif defined(__CYGWIN__)
58  #include <cygwin/version.h>
59 
60  extern long _get_osfhandle (int); /* in cygwin1.dll (no prototype) */
61 #endif
62 
63 static int sk_block = 0; /* sock_daemon() semaphore */
64 static int sk_last = SK_FIRST+1; /* highest socket number + 1 */
65 static Socket *sk_list = NULL;
66 static DWORD raw_seq = 0;
67 
68 static int (*tcp_syn_hook) (_tcp_Socket **tcp) = NULL;
69 static int (*ip4_raw_hook) (const in_Header *ip) = NULL;
70 
71 #if defined(USE_IPV6)
72 static int (*ip6_raw_hook) (const in6_Header *ip) = NULL;
73 #endif
74 
78 #define SOCK_HASH_SIZE 64 /* must be 2^n */
79 
80 static Socket *sk_hashes [SOCK_HASH_SIZE];
81 
82 #if 0
83  static __inline Socket *sock_hash_get (int fd)
84  {
85  return sk_hashes [fd & (SOCK_HASH_SIZE-1)];
86  }
87  static __inline void sock_hash_add (int fd, Socket *sock)
88  {
89  sk_hashes [fd & (SOCK_HASH_SIZE-1)] = sock;
90  }
91 #else
92  #define sock_hash_get(fd) sk_list
93  #define sock_hash_add(fd,sock) ((void)0)
94 #endif
95 
99 void *_sock_calloc (size_t size, const char *file, unsigned line)
100 {
101  void *ptr;
102 
103 #if defined(WATCOM386) && 0 /* find DOS4GW bug! */
104  int rc = _heapset (0xCC);
105 
106  if (rc != _HEAPOK && rc != _HEAPEMPTY)
107  SOCK_FATAL (("%s (%u) Fatal: heap corrupt\n", file, line));
108 #endif
109 
110 #if defined(USE_FORTIFY)
111  ptr = Fortify_calloc (size, 1, file, line);
112 #elif defined(_CRTDBG_MAP_ALLOC) /* MSVC _DEBUG */
113  ptr = _calloc_dbg (size, 1, _NORMAL_BLOCK, file, (int)line);
114 #else
115  ptr = calloc (size, 1);
116 #endif
117 
118  if (!ptr)
119  {
120 #if defined(WATCOM386) && 0 /* find DOS4GW bug! */
121  struct _heapinfo hi;
122  _heapwalk (&hi);
123 #endif
124  SOCK_FATAL (("%s (%u) Fatal: Allocation failed\n", file, line));
125  }
126 
127  ARGSUSED (file);
128  ARGSUSED (line);
129  return (ptr);
130 }
131 
132 
148 static fd_set inuse [NUM_SOCK_FDSETS]; /* MAX_SOCKETS/8 = 625 bytes */
149 
150 static int sock_alloc_fd (char **err)
151 {
152  int fd;
153 
154  *err = NULL;
155 
156 #if defined(__DJGPP__) && defined(USE_FSEXT)
157  {
158  static char err_buf[100];
159 
160  err_buf[0] = '\0';
161  fd = __FSEXT_alloc_fd (_fsext_demux);
162 
163  if (fd < 0)
164  {
165  sprintf (err_buf, "FSEXT_alloc_fd() failed; %s", strerror(errno));
166  *err = err_buf;
167  return (-1);
168  }
169 
170  if (FD_ISSET(fd,&inuse[0]))
171  {
172  sprintf (err_buf, "Reusing existing socket %d", fd);
173  *err = err_buf;
174  return (-1);
175  }
176  }
177 
178 #if (DJGPP_MINOR >= 4) && 0
179  {
180  char dev_name[20];
181 
182  snprintf (dev_name, sizeof(dev_name), "/dev/socket/%d", fd);
183  __set_fd_properties (fd, dev_name, 0); /* last arg? */
184  __set_fd_flags (fd, FILE_DESC_TEMPORARY); /* auto close socket */
185  }
186 #endif
187 
188 #else /* __DJGPP__ && USE_FSEXT */
189 
190  for (fd = SK_FIRST; fd < sk_last; fd++)
191  if (!FD_ISSET(fd,&inuse[0]) && /* not marked as in-use */
192  !_socklist_find(fd)) /* don't use a dying socket */
193  break;
194 
195 #endif /* __DJGPP__ && USE_FSEXT */
196 
197  if (fd < MAX_SOCKETS)
198  {
199  if (fd == sk_last)
200  sk_last++;
201 
202  FD_SET (fd, &inuse[0]);
203  return (fd);
204  }
205 
206  /* No vacant bits in 'inuse' array. djgpp (and DOS) could theoretically
207  * return a file-handle > 'MAX_SOCKETS-1'.
208  */
209  *err = (char*) "No more sockets";
210  return (-1);
211 }
212 
222 BOOL _sock_dos_fd (int s)
223 {
224  if (s >= fileno(stdin) && s <= fileno(stderr)) /* 0..2 (redirected) */
225  return (TRUE);
226 
227  if (s > fileno(stderr) && isatty(s))
228  return (TRUE);
229 
230 #if defined(WIN32)
231  {
232  HANDLE hnd = (HANDLE) _get_osfhandle (s);
233  if (hnd != INVALID_HANDLE_VALUE)
234  {
235  CloseHandle (hnd);
236  return (TRUE);
237  }
238  }
239 #endif
240 
241  return (FALSE);
242 }
243 
252 int _sock_set_rcv_buf (sock_type *s, size_t len)
253 {
254  len = min (len+8,USHRT_MAX); /* add room for head/tail markers */
255  return sock_setbuf (s, (BYTE*)malloc(len), len);
256 
257  /* Note: the ret-val from above malloc() is freed below.
258  * Normally via tcp_daemon(). The freeing can take some time.
259  * Hence reports about memory leaks (from e.g. MSVC debug-builds)
260  * are not so important.
261  */
262 }
263 
268 {
269  if (s->tcp.rx_data && /* if xx_open() called */
270  s->tcp.rx_data != &s->tcp.rx_buf[0])
271  {
272  *(DWORD*)(s->tcp.rx_data-4) = 0; /* clear marker */
273  free (s->tcp.rx_data-4);
274  s->tcp.rx_data = &s->tcp.rx_buf[0];
275  s->tcp.rx_datalen = 0;
276  }
277 }
278 
284 static __inline Socket *sk_list_del (int s)
285 {
286  Socket *sock, *last, *next;
287 
288  for (sock = last = sock_hash_get(s); sock; last = sock, sock = next)
289  {
290  next = sock->next;
291  if (sock->fd != s)
292  continue;
293 
294  if (sock == sk_list)
295  sk_list = next;
296  else last->next = next;
297  sock_hash_add (s, NULL);
298  free (sock);
299  return (next);
300  }
301  return (NULL);
302 }
303 
308 const sock_type *__get_sock_from_s (int s, int proto)
309 {
310  Socket *sock = _socklist_find (s);
311 
312  if (!sock)
313  return (NULL);
314 
315  if (proto == UDP_PROTO)
316  return (sock_type*) sock->udp_sock;
317 
318  if (proto == TCP_PROTO)
319  return (sock_type*) sock->tcp_sock;
320 
321  if (proto == IPPROTO_IP)
322  return (sock_type*) sock->raw_sock;
323 
324  return (NULL);
325 }
326 
331 static __inline BOOL other_tcp_listeners (const Socket *_this)
332 {
333  const Socket *sock;
334 
335  for (sock = sk_list; sock; sock = sock->next)
336  if (sock->so_type == SOCK_STREAM &&
337  (sock->so_options & SO_ACCEPTCONN) &&
338  sock != _this)
339  return (TRUE);
340  return (FALSE);
341 }
342 
343 void _sock_set_syn_hook (int (*func)(_tcp_Socket**))
344 {
345  tcp_syn_hook = func;
346 }
347 
352 static __inline BOOL other_raw_socks (const Socket *_this)
353 {
354  const Socket *sock;
355 
356  for (sock = sk_list; sock; sock = sock->next)
357  if (sock->so_type == SOCK_RAW && sock != _this)
358  return (TRUE);
359  return (FALSE);
360 }
361 
366 static BOOL mcast_set = FALSE;
367 static BOOL promis_set = FALSE;
368 
369 BOOL _sock_set_normal_rx_mode (const Socket *_this)
370 {
371  const Socket *sock;
372  BOOL rc = TRUE;
373 
374 #if defined(USE_MULTICAST)
375  if (num_mcast_active() > 0)
376  return (rc);
377 #endif
378 
379  for (sock = sk_list; sock; sock = sock->next)
380  if (sock != _this &&
381  (sock->so_family == AF_INET6 || sock->so_type == SOCK_PACKET))
382  break;
383 
384  if (!sock)
385  {
387  if (!rc)
388  SOCK_DEBUGF (("\n setting normal rx-mode failed; %s",
391  mcast_set = FALSE;
392  }
393  return (rc);
394 }
395 
396 BOOL _sock_set_mcast_rx_mode (void)
397 {
398  BOOL rc = TRUE;
399 
400  if (!mcast_set)
401 #if defined(USE_IPV6)
402  rc = _ip6_pkt_init();
403 #else
405 #endif
406 
407  mcast_set = TRUE;
408  return (rc);
409 }
410 
411 BOOL _sock_set_promisc_rx_mode (void)
412 {
413  BOOL rc = TRUE;
414 
415  if (!promis_set)
417  promis_set = TRUE;
418  return (rc);
419 }
420 
424 static void sock_raw_del (Socket *sock)
425 {
426 #if defined(USE_IPV6)
427  if (sock->so_family == AF_INET6)
428  {
429  _raw6_Socket *raw, *next;
430 
431  if (!other_raw_socks(sock))
432  ip6_raw_hook = NULL;
433 
434  for (raw = sock->raw6_sock; raw; raw = next)
435  {
436  raw->ip_type = 0;
437  next = raw->next;
438  free (raw);
439  }
440  sock->raw6_sock = NULL;
441  }
442  else
443 #endif
444  {
445  _raw_Socket *raw, *next;
446 
447  if (!other_raw_socks(sock))
448  ip4_raw_hook = NULL;
449 
450  for (raw = sock->raw_sock; raw; raw = next)
451  {
452  raw->ip_type = 0;
453  next = raw->next;
454  free (raw);
455  }
456  sock->raw_sock = NULL;
457  }
458 }
459 
463 static BOOL sock_packet_add (Socket *sock)
464 {
465  sock_packet_pool *p = SOCK_CALLOC (sizeof(*p));
466 
467  sock->packet_pool = p;
468  if (!sock->packet_pool)
469  return (FALSE);
470  pktq_init (&p->queue, sizeof(p->buf[0]), DIM(p->buf), (char*)p->buf);
471  return (TRUE);
472 }
473 
474 static void sock_packet_del (Socket *sock)
475 {
476  if (sock->packet_pool)
477  {
478  /* SOCK_DEBUGF ((", num-drops %lu", sock->packet_pool->queue.num_drop); */
479  free (sock->packet_pool);
480  }
481  sock->packet_pool = NULL;
482  _eth_recv_peek = sock->old_eth_peek;
483 }
484 
485 /*
486  * Receiver for SOCK_PACKET sockets
487  */
488 static int W32_CALL sock_packet_peek (const union link_Packet *pkt)
489 {
490  Socket *sock, *last = NULL;
491 
492  for (sock = sk_list; sock; sock = sock->next)
493  if (sock->so_type == SOCK_PACKET && sock->packet_pool)
494  {
495  struct pkt_ringbuf *q = &sock->packet_pool->queue;
496  struct sock_packet_buf *rx;
497  size_t len;
498 
499 #if defined(USE_DEBUG)
500  if (!pktq_check(q))
501  {
502  TCP_CONSOLE_MSG (0, ("%s(%u): SOCK_PACKET queue munged, "
503  "fd %d\n", __FILE__, __LINE__, sock->fd));
504  pktq_clear (q);
505  continue;
506  }
507 #endif
508  if (pktq_in_index(q) == q->out_index) /* no room */
509  {
510  q->num_drop++;
511  TCP_CONSOLE_MSG (0, ("SOCK_PACKET drops %lu\n", q->num_drop));
512  continue;
513  }
514 
515  rx = (struct sock_packet_buf*) pktq_in_buf (q);
516 
517  if (_eth_last.rx.size > 0) /* Only for Win32 or USE_FAST_PKT */
518  len = _eth_last.rx.size;
519  else len = sizeof(rx->rx_buf) - 4;
520 
521  memcpy (rx->rx_buf, pkt, len);
522  rx->rx_len = len;
523  pktq_inc_in (q);
524  last = sock;
525  }
526 
527  if (last && last->old_eth_peek && last->old_eth_peek != _eth_recv_peek)
528  return (*last->old_eth_peek) ((void*)pkt);
529  return (1);
530 }
531 
535 static char get_pkt_type_eth (const eth_Header *eth)
536 {
537  if (!memcmp(&_eth_addr,&eth->destination,_eth_mac_len))
538  return (PACKET_HOST);
539  if (!memcmp(&_eth_addr,&eth->source,_eth_mac_len))
540  return (PACKET_OUTGOING);
541  if (!memcmp(&eth->destination,&_eth_brdcast,_eth_mac_len))
542  return (PACKET_BROADCAST);
543  if ((eth->destination[0] & 1) == 1)
544  return (PACKET_MULTICAST);
545  return (PACKET_OTHERHOST); /* To someone else */
546 }
547 
548 static char get_pkt_type_fddi (const fddi_Header *fddi)
549 {
550  if (!memcmp(&_eth_addr,&fddi->destination,_eth_mac_len))
551  return (PACKET_HOST);
552  if (!memcmp(&_eth_addr,&fddi->source,_eth_mac_len))
553  return (PACKET_OUTGOING);
554  if (!memcmp(&fddi->destination,&_eth_brdcast,_eth_mac_len))
555  return (PACKET_BROADCAST);
556  if ((fddi->destination[0] & 1) == 1)
557  return (PACKET_MULTICAST);
558  return (PACKET_OTHERHOST); /* To someone else */
559 }
560 
561 static char get_pkt_type_tok (const tok_Header *tok)
562 {
563  if (!memcmp(&_eth_addr,&tok->destination,_eth_mac_len))
564  return (PACKET_HOST);
565  if (!memcmp(&_eth_addr,&tok->source,_eth_mac_len))
566  return (PACKET_OUTGOING);
567  if (!memcmp(&tok->destination,&_eth_brdcast,_eth_mac_len))
568  return (PACKET_BROADCAST);
569  if ((tok->destination[0] & 1) == 1)
570  return (PACKET_MULTICAST);
571  return (PACKET_OTHERHOST); /* To someone else */
572 }
573 
574 static char get_pkt_type_arc (const arcnet_Header *arc)
575 {
576  ARGSUSED (arc);
577  return (PACKET_HOST);
578 }
579 
580 static char get_pkt_type (const union link_Packet *pkt)
581 {
582  switch (_pktdevclass)
583  {
584  case PDCLASS_TOKEN:
585  return get_pkt_type_tok (&pkt->tok.head);
586  case PDCLASS_FDDI:
587  return get_pkt_type_fddi (&pkt->fddi.head);
588  case PDCLASS_ARCNET:
589  return get_pkt_type_arc (&pkt->arc.head);
590  case PDCLASS_ETHER:
591  return get_pkt_type_eth (&pkt->eth.head);
592  default:
593  return (PACKET_HOST); /* to us (assuming PPP/SLIP) */
594  }
595 }
596 
601 unsigned sock_packet_receive (Socket *sock, void *buf, unsigned len,
602  struct sockaddr *from, size_t *fromlen)
603 {
604  struct pkt_ringbuf *q;
605  struct sock_packet_buf *rx;
606 
607  if (!sock->packet_pool)
608  return (0);
609 
610  q = &sock->packet_pool->queue;
611  if (q->in_index == q->out_index) /* no elements */
612  return (0);
613 
614  rx = (struct sock_packet_buf*) pktq_out_buf (q);
615  len = min (len, rx->rx_len);
616  memcpy (buf, rx->rx_buf, len);
617 
618  if (from && fromlen)
619  {
620  struct sockaddr_ll *sa = (struct sockaddr_ll*) from;
621  BYTE hw_type, hw_len;
622 
623  _eth_get_hwtype (&hw_type, &hw_len);
624  memset (from, 0, sizeof(*sa));
625  sa->sll_halen = hw_len;
626  sa->sll_hatype = hw_type;
627  sa->sll_protocol = *(WORD*) ((char*)buf+_pkt_ip_ofs-2);
628  sa->sll_ifindex = 1;
629  sa->sll_family = AF_PACKET;
630  sa->sll_pkttype = get_pkt_type ((const union link_Packet*)buf);
631  *fromlen = sizeof (*sa);
632  }
633  pktq_inc_out (q);
634  return (len);
635 }
636 
637 /*
638  * Needed by select_s().
639  */
640 unsigned sock_packet_rbused (Socket *sock)
641 {
642  if (!sock->packet_pool)
643  return (0);
644  return pktq_queued (&sock->packet_pool->queue);
645 }
646 
647 unsigned sock_packet_transmit (Socket *socket, const void *buf, unsigned len,
648  const struct sockaddr *to, int tolen)
649 {
650  const struct sockaddr_ll *sa = (const struct sockaddr_ll*) to;
651  BYTE *tx;
652  int rc;
653 
654  if (len <= _pkt_ip_ofs)
655  {
656  SOCK_ERRNO (EINVAL);
657  return (-1);
658  }
659  tx = _eth_formatpacket (sa ? &sa->sll_addr : NULL,
660  sa ? sa->sll_protocol : 0);
661  tx -= _pkt_ip_ofs;
662  len = min (len, sizeof(union link_Packet));
663  memcpy (tx, buf, len);
664  rc = _eth_send (len - _pkt_ip_ofs, NULL, __FILE__, __LINE__);
665  if (rc <= 0)
666  return (-1);
667 
668  ARGSUSED (socket);
669  ARGSUSED (tolen); /* already checked by caller */
670  return (rc + _pkt_ip_ofs);
671 }
672 
673 
674 /*
675  * Clear 'fd' from the inuse array. For djgpp only:
676  * Free the socket from File-System Extension system.
677  * Free the duplicated handle from DOS's System File Table.
678  */
679 static void sock_close_fd (int fd)
680 {
681  if (fd >= SK_FIRST && fd < MAX_SOCKETS)
682  {
683  FD_CLR (fd, &inuse[0]);
684  if (fd == sk_last-1)
685  sk_last--;
686  }
687 
688 #if defined(__DJGPP__) && defined(USE_FSEXT)
689  __FSEXT_set_function (fd, NULL);
690  if (fd >= SK_FIRST && _close(fd) < 0)
691  SOCK_DEBUGF ((" _close() failed; %s", strerror(errno)));
692 #endif
693 }
694 
701 Socket *_sock_del_fd (int fd, const char *file, unsigned line)
702 {
703  Socket *sock, *next = NULL;
704  sock_type *sk;
705 
706  SOCK_DEBUGF (("\n _sock_del_fd:%d", fd));
707 
708  if (fd < SK_FIRST || fd >= sk_last || !FD_ISSET(fd,&inuse[0]))
709  {
710  SOCK_FATAL (("%s (%u) Fatal: socket %d not inuse\n", file, line, fd));
711  return (NULL);
712  }
713 
714  sock = _socklist_find (fd);
715  if (!sock)
716  {
717  SOCK_FATAL (("%s (%u) Fatal: socket %d not in list\n", file, line, fd));
718  goto not_inuse;
719  }
720 
721  if (sock->cookie != SAFETY_TCP) /* Aaarg! marker destroyed */
722  {
723  SOCK_FATAL (("%s (%u) fatal: socket %d (%p) overwritten\n",
724  file, line, fd, sock));
725  goto not_inuse;
726  }
727 
728  switch (sock->so_type)
729  {
730  case SOCK_STREAM:
731  sk = (sock_type*) sock->tcp_sock;
732  if (sk)
733  {
734  reuse_localport (sk->tcp.myport); /* clear 'lport_inuse' bit now */
735  TCP_ABORT (&sk->tcp);
736  _sock_free_rcv_buf (sk);
737  }
738  DO_FREE (sock->tcp_sock);
739  if (!other_tcp_listeners(sock))
740  _sock_set_syn_hook (NULL);
741  break;
742 
743  case SOCK_DGRAM:
744  sk = (sock_type*) sock->udp_sock;
745  if (sk)
746  {
747  reuse_localport (sk->udp.myport); /* redundant? */
748  sock_abort (sk);
749  _sock_free_rcv_buf (sk);
750  }
751  DO_FREE (sock->udp_sock);
752  break;
753 
754  case SOCK_RAW:
755  sock_raw_del (sock);
756  break;
757 
758  case SOCK_PACKET:
759  sock_packet_del (sock);
760  break;
761 
762  default:
763  SOCK_DEBUGF (("\n _sock_del_fd:%d: unknown type %d",
764  fd, sock->so_type));
765  break;
766  }
767 
768  DO_FREE (sock->local_addr);
769  DO_FREE (sock->remote_addr);
770  DO_FREE (sock->ip_opt);
771  DO_FREE (sock->bcast_pool);
772  DO_FREE (sock->packet_pool);
773 
774  /* Check for any remaining IPv6/PACKET sockets.
775  */
776  if ((sock->so_family == AF_INET6 || sock->so_type == SOCK_PACKET) &&
777  _pkt_rxmode > RXMODE_BROADCAST && /* current Rx-mode not broadcast */
778  _pkt_forced_rxmode < 0) /* we didn't force a specific mode */
779  _sock_set_normal_rx_mode (sock); /* Then set normal Rx-mode */
780 
781  next = sk_list_del (fd); /* delete socket from linked list */
782 
783  if (sk_list == NULL) /* no more sockets, hook not needed */
784  _bsd_socket_hook = NULL;
785 
786 not_inuse:
787  sock_close_fd (fd);
788  ARGSUSED (file);
789  ARGSUSED (line);
790  return (next);
791 }
792 
793 #ifdef NOT_USED
794 
798 static int sock_find_fd (const Socket *socket)
799 {
800  const Socket *sock;
801 
802  for (sock = sock_hash_get(socket->fd); sock; sock = sock->next)
803  if (sock == socket)
804  return (sock->fd);
805  return (-1);
806 }
807 
812 static Socket *sock_find_udp (const _udp_Socket *udp)
813 {
814  Socket *sock;
815 
816  for (sock = sk_list; sock; sock = sock->next)
817  if (sock->udp_sock == udp)
818  return (sock);
819  return (NULL);
820 }
821 #endif /* NOT_USED */
822 
826 static void *sock_find_tcp (const _tcp_Socket *tcp)
827 {
828  Socket *sock;
829 
830  for (sock = sk_list; sock; sock = sock->next)
831  if (sock->tcp_sock == tcp)
832  return (void*)sock;
833  return (NULL);
834 }
835 
839 int _sock_chk_sockaddr (Socket *socket, const struct sockaddr *sa, int len)
840 {
841  int sa_len = (socket->so_family == AF_INET6) ? sizeof(struct sockaddr_in6) :
842  sizeof(struct sockaddr_in);
843  if (!sa || len < sa_len)
844  {
845  SOCK_DEBUGF ((", EINVAL"));
846  SOCK_ERRNO (EINVAL);
847  return (-1);
848  }
849 
850  if (socket->so_type == SOCK_PACKET)
851  {
852  SOCK_DEBUGF ((", SOCK_PACKET, EAFNOSUPPORT"));
853  SOCK_ERRNO (EAFNOSUPPORT);
854  return (-1);
855  }
856 
857  /* Easy way to reconnect a UDP socket.
858  */
859  if (sa->sa_family == AF_UNSPEC && socket->so_type == SOCK_DGRAM)
860  {
861  socket->so_state &= ~(SS_ISDISCONNECTING | SS_CANTSENDMORE);
862  socket->udp_sock->rx_datalen = 0; /* flush recv buf */
863  if (socket->remote_addr)
864  free (socket->remote_addr);
865  socket->remote_addr = NULL;
866 
867  SOCK_DEBUGF ((", AF_UNSPEC, EAFNOSUPPORT"));
868  SOCK_ERRNO (EAFNOSUPPORT);
869  return (-1);
870  }
871 
872  if (sa->sa_family != socket->so_family)
873  {
874  SOCK_DEBUGF ((", different families"));
875  SOCK_ERRNO (EAFNOSUPPORT);
876  return (-1);
877  }
878 
879  VERIFY_RW (sa, len);
880  return (0);
881 }
882 
886 static struct _raw_Socket *find_free_raw_sock (Socket *sock)
887 {
888  struct _raw_Socket *raw;
889 
890  if (!sock->raw_sock)
891  SOCK_FATAL (("find_raw_sock() called for non-raw sock, so_type %d\n",
892  sock->so_type));
893 
894  for (raw = sock->raw_sock; raw; raw = raw->next)
895  if (!raw->used)
896  return (raw);
897  return (NULL);
898 }
899 
900 #if defined(USE_IPV6)
901 static struct _raw6_Socket *find_free_raw6_sock (Socket *sock)
902 {
903  struct _raw6_Socket *raw;
904 
905  if (!sock->raw6_sock)
906  SOCK_FATAL (("find_raw6_sock() called for non-raw sock, so_type %d\n",
907  sock->so_type));
908 
909  for (raw = sock->raw6_sock; raw; raw = raw->next)
910  if (!raw->used)
911  return (raw);
912  return (NULL);
913 }
914 #endif
915 
925 static int sock_raw4_recv (const in_Header *ip)
926 {
927  Socket *sock;
928  _raw_Socket *raw;
929  int num_enqueued = 0;
930  size_t len = ntohs (ip->length);
931 
932  /* Early drop; jumbo packets won't match any raw-sockets
933  */
934  if (len > sizeof(sock->raw_sock->rx_data))
935  return (0);
936 
937  /* Should SOCK_RAW allow packets not destined to us *and* not
938  * broadcast? Yes for now.
939  */
940 #if 0
941  {
942  DWORD ip_dst = ntohl (ip->destination);
943 
944  /* Not addressed to us or not (limited) broadcast
945  */
946  if (!_ip4_is_local_addr(ip_dst) && !_ip4_is_ip_brdcast(ip))
947  return (0);
948  }
949 #endif
950 
951  for (sock = sk_list; sock; sock = sock->next)
952  {
953  if (sock->so_type != SOCK_RAW)
954  continue;
955 
956  if (sock->so_proto == IPPROTO_IP)
957  goto enqueue; /* socket matches every IP-protocol, enqueue */
958 
959  if (ip->proto != sock->so_proto) /* isn't what we want */
960  continue;
961 
962  enqueue:
963  raw = find_free_raw_sock (sock);
964  if (!raw)
965  {
966 #if 1 /* Maybe user didn't bother to read it. Ignore it. */
967  SOCK_DEBUGF (("\n socket:%d, dropped raw (IP4), proto %d, id %04X",
968  sock->fd, ip->proto, ntohs(ip->identification)));
969 #endif
970  continue;
971  }
972 
973  /* Copy IP-header to raw_sock.ip
974  */
975  memcpy (&raw->ip, ip, sizeof(*ip));
976 
977  /* Copy any options and rest of IP-packet
978  */
979  memcpy (&raw->rx_data[0], ip+1, min(len,sizeof(raw->rx_data)));
980  raw->used = TRUE;
981  raw->seq_num = ++raw_seq;
982  num_enqueued++;
983 
984  if (sock->so_options & SO_DEBUG)
985  {
986  /*\todo Add SOCK_RAW debug */
987  }
988  }
989  return (num_enqueued);
990 }
991 
992 #if defined(USE_IPV6)
993 static int sock_raw6_recv (const in6_Header *ip)
994 {
995  Socket *sock;
996  _raw6_Socket *raw;
997  int num_enqueued = 0;
998  int num_dropped = 0;
999  const void *dest = &ip->destination[0];
1000  size_t len = ntohs (ip->len);
1001 
1002  /* Jumbo packets won't match any raw-sockets
1003  */
1004  if (len > sizeof(sock->raw6_sock->rx_data))
1005  return (0);
1006 
1007  /* Not addressed to us or not multicast
1008  */
1009  if (memcmp(&in6addr_my_ip,dest,sizeof(in6addr_my_ip)) &&
1010  !IN6_IS_ADDR_MULTICAST(dest))
1011  return (0);
1012 
1013  for (sock = sk_list; sock; sock = sock->next)
1014  {
1015  if (ip->next_hdr == IPPROTO_TCP && sock->so_type == SOCK_STREAM)
1016  continue;
1017 
1018  if (ip->next_hdr == IPPROTO_UDP && sock->so_type == SOCK_DGRAM)
1019  continue;
1020 
1021  if (sock->so_type != SOCK_RAW ||
1022  (ip->next_hdr != sock->so_proto && sock->so_proto != IPPROTO_IP))
1023  continue;
1024 
1025  raw = find_free_raw6_sock (sock);
1026  if (!raw)
1027  {
1028  num_dropped++;
1029  SOCK_DEBUGF (("\n socket:%d, dropped raw (IP6), proto %d",
1030  sock->fd, ip->next_hdr));
1031  }
1032  else
1033  {
1034  /* Copy IP-header to raw6_sock.ip
1035  */
1036  memcpy (&raw->ip6, ip, sizeof(*ip));
1037 
1038  /* Copy rest of IP-packet (no optios)
1039  */
1040  memcpy (&raw->rx_data[0], ip+1, min(len,sizeof(raw->rx_data)));
1041  raw->used = TRUE;
1042  raw->seq_num = ++raw_seq;
1043  num_enqueued++;
1044 
1045  if (sock->so_options & SO_DEBUG)
1046  {
1047  /*\todo Add SOCK_RAW debug */
1048  }
1049  }
1050  }
1051 
1052  if (num_dropped > 0)
1053  STAT (ip4stats.ips_idropped++);
1054 
1055  return (num_enqueued);
1056 }
1057 #endif /* USE_IPV6 */
1058 
1063 static void do_keepalive (Socket *sock)
1064 {
1065  if (sock->keepalive == 0)
1066  {
1067  if (tcp_keep_idle)
1068  sock->keepalive = set_timeout (1000 * tcp_keep_idle);
1069  }
1070  else if (sock->tcp_sock->locflags & LF_KEEPALIVE)
1071  {
1072  sock->keepalive = 0UL;
1073  }
1074  else if (chk_timeout(sock->keepalive))
1075  {
1076  _tcp_keepalive (sock->tcp_sock);
1077  SOCK_DEBUGF (("\n sock_keepalive:%d", sock->fd));
1078  sock->keepalive = 0UL;
1079  }
1080 }
1081 
1086 static void * MS_CDECL socket_op_demux (enum BSD_SOCKET_OPS op, ...)
1087 {
1088  const _tcp_Socket *tcp;
1089  void *rc = NULL;
1090  Socket *sock;
1091  va_list args;
1092 
1093  va_start (args, op);
1094 
1095  switch (op)
1096  {
1097  case BSO_FIND_SOCK: /* return a 'Socket*' from '_tcp_Socket*' */
1098  tcp = va_arg (args, const _tcp_Socket*);
1099  if (tcp->ip_type == TCP_PROTO)
1100  rc = sock_find_tcp (tcp);
1101  else rc = NULL;
1102  break;
1103 
1104  case BSO_RST_CALLBACK: /* RST received in _tcp_handler() */
1105  tcp = va_arg (args, const _tcp_Socket*);
1106  sock = sock_find_tcp (tcp);
1107  if (sock)
1108  {
1109  sock->so_error = ECONNRESET;
1110  SOCK_DEBUGF (("\n TCP-reset:%d", sock->fd));
1111  if (tcp->rx_datalen == 0)
1112  {
1113  sock->so_state |= (SS_CONN_REFUSED | SS_CANTSENDMORE | SS_CANTRCVMORE);
1114  sock->close_time = time (NULL);
1115  sock->linger_time = TCP_LINGERTIME/40; /* 3 sec */
1116  }
1117  }
1118  else
1119  SOCK_DEBUGF (("\n TCP-reset for unknown socket??"));
1120  break;
1121 
1122  case BSO_SYN_CALLBACK: /* filtering SYNs in _sock_append() */
1123  if (tcp_syn_hook)
1124  rc = IntToPtr ((*tcp_syn_hook) (va_arg(args,_tcp_Socket**)));
1125  else rc = IntToPtr (1); /* ret-val doesn't matter */
1126  break;
1127 
1128  case BSO_IP4_RAW:
1129  if (ip4_raw_hook)
1130  rc = IntToPtr ((*ip4_raw_hook) (va_arg(args,const in_Header*)));
1131  break;
1132 
1133  case BSO_IP6_RAW:
1134 #if defined(USE_IPV6)
1135  if (ip6_raw_hook)
1136  rc = IntToPtr ((*ip6_raw_hook) (va_arg(args,const in6_Header*)));
1137 #endif
1138  break;
1139 
1140  case BSO_DEBUG: /* \todo trace the in/out state etc. */
1141 #if 0
1142  sk = va_arg (args, const sock_type*);
1143  if (sk->tcp.ip_type == TCP_PROTO)
1144  {
1145  UINT st_in = va_arg (args, UINT);
1146  UINT st_out = va_arg (args, UINT);
1147  (*_printf) ("TCP: %s -> %s\n", st_in, st_out);
1148  }
1149  socket_debugdump (sk);
1150 #endif
1151  break;
1152 
1153  default:
1154  SOCK_FATAL (("%s (%u) Fatal: Unknown op-code %d\n",
1155  __FILE__, __LINE__, op));
1156  break;
1157  }
1158  va_end (args);
1159  return (rc);
1160 }
1161 
1170 {
1171  Socket *next = sock->next;
1172  _tcp_Socket *tcp = sock->tcp_sock;
1173  int s = sock->fd;
1174  int state = tcp->state;
1175 
1176  if (sock->so_options & SO_KEEPALIVE)
1177  do_keepalive (sock);
1178 
1179  if (state == tcp_StateRESOLVE ||
1180  state == tcp_StateSYNSENT) /* opening active tcp session */
1181  {
1182  sock->so_state |= SS_ISCONNECTING;
1183  }
1184  else if (state == tcp_StateESTAB) /* established tcp session */
1185  {
1186  sock->so_state |= SS_ISCONNECTED;
1187  sock->so_state &= ~(SS_ISCONNECTING | SS_ISDISCONNECTING);
1188  }
1189  else if (state >= tcp_StateTIMEWT) /* dying tcp session */
1190  {
1191  sock_type *sk = (sock_type*)tcp;
1192  BOOL closing = (sock->so_state & (SS_ISDISCONNECTING | SS_CANTSENDMORE));
1193 
1194  sock->so_state &= ~(SS_ISCONNECTED | SS_ISCONNECTING);
1195  DO_FREE (sock->ip_opt);
1196 
1197  if (sock->close_time && (sock->so_state & SS_CANTRCVMORE))
1198  {
1199  /* Flush any remaining Rx data received after shutdown(0) called.
1200  */
1201  sock_fastread (sk, NULL, -1);
1202  }
1203 
1204  if (closing && sk->tcp.ip_type == 0) /* fully closed, refused or aborted */
1205  {
1206  BOOL expired = FALSE;
1207 
1208  if (!sock_rbused(sk))
1209  _sock_free_rcv_buf (sk); /* free memory not needed anymore */
1210 
1211  if (sock->close_time) /* close_s() called */
1212  expired = (time(NULL) - sock->close_time >= (time_t)sock->linger_time);
1213 
1214  /* If linger-period expired and fully closed, delete the TCB
1215  */
1216  if (expired && state == tcp_StateCLOSED)
1217  {
1218  SOCK_DEBUGF (("\n tcp_sock_daemon del:%d, lport %d", s, tcp->myport));
1219  next = SOCK_DEL_FD (s);
1220  }
1221  }
1222  }
1223  return (next);
1224 }
1225 
1226 
1237 {
1238  Socket *next = sock->next;
1239  _udp_Socket *udp = sock->udp_sock;
1240 
1241  if ((sock->so_state & (SS_ISDISCONNECTING | SS_CANTSENDMORE)) &&
1242  (udp->rx_datalen == 0 || udp->ip_type == 0))
1243  {
1244  SOCK_DEBUGF (("\n udp_sock_daemon del:%d", sock->fd));
1245  next = SOCK_DEL_FD (sock->fd);
1246  }
1247  return (next);
1248 }
1249 
1256 static void sock_daemon (void)
1257 {
1258  Socket *sock, *next = NULL;
1259 
1260  /* If we're in a critical region (e.g. connect() or select_s()) where
1261  * we don't want our socket-list to change, do this later.
1262  */
1263  if (sk_block)
1264  return;
1265 
1266  for (sock = sk_list; sock; sock = next)
1267  {
1268  next = sock->next;
1269 
1270  if (!FD_ISSET(sock->fd,&inuse[0]))
1271  continue;
1272 
1273  if (sock->local_addr == NULL) /* not bound to anything yet */
1274  continue;
1275 
1276  switch (sock->so_type)
1277  {
1278  case SOCK_STREAM:
1279  if (sock->tcp_sock)
1280  next = tcp_sock_daemon (sock);
1281  break;
1282  case SOCK_DGRAM:
1283  if (sock->udp_sock)
1284  next = udp_sock_daemon (sock);
1285  break;
1286  }
1287  }
1288 }
1289 
1290 
1296 void _sock_crit_start (void)
1297 {
1298  if (sk_block < INT_MAX)
1299  ++sk_block;
1300 }
1301 
1306 void _sock_crit_stop (void)
1307 {
1308  if (sk_block > 0)
1309  {
1310  --sk_block;
1311 
1312 #ifdef SIGALRM
1313 #endif
1314 
1315  if (sk_block == 0)
1316  sock_daemon(); /* run blocked sock_daemon() */
1317  }
1318 }
1319 
1320 
1321 #if defined(USE_FORTIFY) && defined(USE_DEBUG)
1322 
1326 static void sock_fortify_exit (void)
1327 {
1328  const Socket *sock;
1329 
1330  if (!_sock_dbug_active())
1331  return;
1332 
1333  for (sock = sk_list; sock; sock = sock->next)
1334  {
1335  const char *type = "<?>";
1336  const void *wsock = NULL;
1337  const _tcp_Socket *tcp;
1338 
1339  if (sock->cookie != SAFETY_TCP ||
1340  sock->fd < SK_FIRST ||
1341  sock->fd >= sk_last)
1342  {
1343  SOCK_DEBUGF (("\nsk_list munged; sock->fd = %d", sock->fd));
1344  return;
1345  }
1346 
1347  switch (sock->so_type)
1348  {
1349  case SOCK_STREAM:
1350  type = "TCP";
1351  wsock = sock->tcp_sock;
1352  break;
1353 
1354  case SOCK_DGRAM:
1355  type = "UDP";
1356  wsock = sock->udp_sock;
1357  break;
1358 
1359  case SOCK_PACKET:
1360  type = "Packet";
1361  wsock = sock->packet_pool;
1362  break;
1363 
1364  case SOCK_RAW:
1365 #if defined(USE_IPV6)
1366  if (sock->so_family == AF_INET6)
1367  {
1368  type = "Raw6";
1369  wsock = sock->raw6_sock;
1370  }
1371  else
1372 #endif
1373  {
1374  type = "Raw";
1375  wsock = sock->raw_sock;
1376  }
1377  break;
1378  }
1379 
1380  SOCK_DEBUGF (("\n%2d: inuse %d, type %s, watt-sock %08lX",
1381  sock->fd, FD_ISSET(sock->fd,&inuse[0]) ? 1 : 0,
1382  type, (DWORD_PTR)wsock));
1383 
1384  tcp = sock->tcp_sock;
1385  if (tcp)
1386  {
1387  if (sock->so_state & SS_ISDISCONNECTING)
1388  SOCK_DEBUGF ((" (closed"));
1389  else if (sock->so_state & SS_ISLISTENING)
1390  SOCK_DEBUGF ((" (listening"));
1391  else SOCK_DEBUGF ((" (aborted?"));
1392  SOCK_DEBUGF ((", %s)", tcpStateName(tcp->state)));
1393  }
1394  }
1395 
1396  SOCK_DEBUGF ((" \n"));
1397  Fortify_OutputStatistics();
1398  Fortify_LeaveScope();
1399 }
1400 #endif /* USE_FORTIFY && USE_DEBUG */
1401 
1402 
1403 #if defined(USE_DEBUG) && defined(ERRNO_VENDOR_VERSION)
1404 
1407 static const char *vendor_version (void)
1408 {
1409  static char buf[10];
1410 
1411 #if defined(__DJGPP__)
1412  sprintf (buf, "%d.%02d", __DJGPP__, __DJGPP_MINOR__);
1413 
1414 #elif defined(__DMC__)
1415  sprintf (buf, "%X.%X", __DMC__ >> 8, __DMC__ & 0xFF);
1416 
1417 #elif defined(__WATCOMC__)
1418  sprintf (buf, "%d.%d", __WATCOMC__/100, __WATCOMC__ % 100);
1419 
1420 #elif defined(__BORLANDC__)
1421  sprintf (buf, "%X.%X", __BORLANDC__ >> 8, __BORLANDC__ & 0xFF);
1422 
1423 #elif defined(__TURBOC__)
1424  sprintf (buf, "%X.%X", (__TURBOC__ >> 8) - 1, __TURBOC__ & 0xFF);
1425 
1426 #elif defined(_MSC_VER)
1427  sprintf (buf, "%d.%d", _MSC_VER/100, _MSC_VER % 100);
1428 
1429 #elif defined(__MINGW32__) && defined(__MINGW64_VERSION_MAJOR)
1430  /* __MINGW64_VERSION_[MAJOR|MINOR] is defined through _mingw.h in MinGW-W64 */
1431  sprintf (buf, "%d.%d", __MINGW64_VERSION_MAJOR, __MINGW64_VERSION_MINOR);
1432 
1433 #elif defined(__MINGW32__) /* mingw.org MinGW. MingW-RT-4+ defines '__MINGW_MAJOR_VERSION' */
1434  #if defined(__MINGW_MAJOR_VERSION)
1435  sprintf (buf, "%d.%d", __MINGW_MAJOR_VERSION, __MINGW_MINOR_VERSION);
1436  #else
1437  sprintf (buf, "%d.%d", __MINGW32_MAJOR_VERSION, __MINGW32_MINOR_VERSION);
1438  #endif
1439 
1440 #elif defined(__CYGWIN__) /* this should be dead code for CygWin */
1441  sprintf (buf, "%d.%d", CYGWIN_VERSION_DLL_MAJOR, CYGWIN_VERSION_DLL_MINOR);
1442 
1443 #elif defined(__CCDL__)
1444  sprintf (buf, "%d.%d", __CCDL__/100, __CCDL__ % 100);
1445 
1446 #else
1447  buf[0] = '\0';
1448 #endif
1449 
1450  return (buf);
1451 }
1452 
1457 static void check_errno_version (void)
1458 {
1459  const char *ver = vendor_version();
1460 
1461  if (*ver && strcmp(ver,ERRNO_VENDOR_VERSION))
1462  {
1463  (*_printf) ("\nWarning: %%WATT_ROOT%%\\inc\\sys\\*.err was created "
1464  "with a different compiler\nversion (%s vs %s). "
1465  "Rebuilt %%WATT_ROOT%%\\util\\*_err.exe and "
1466  "Watt-32 library to avoid subtle bugs.\n",
1467  ERRNO_VENDOR_VERSION, ver);
1468  BEEP();
1469  }
1470 }
1471 #endif /* USE_DEBUG && ERRNO_VENDOR_VERSION */
1472 
1473 
1483 static BOOL init_sockets (void)
1484 {
1485  static int sk_result = -1;
1486 
1487  if (sk_result >= 0)
1488  return (sk_result);
1489 
1490  /* Hack to make linker pull in our strerror().
1491  */
1492  pull_neterr_module = 0;
1493 
1494  _watt_do_exit = 0;
1495  sk_result = (watt_sock_init(0,0,0) == 0);
1496  if (!sk_result)
1497  return (FALSE);
1498 
1499 #if defined(USE_DEBUG) && defined(ERRNO_VENDOR_VERSION)
1501 #endif
1502 
1503 #ifdef __DJGPP__
1504  {
1505  struct rlimit r;
1506 
1507  getrlimit (RLIMIT_NOFILE, &r);
1508  r.rlim_max = MAX_SOCKETS; /* We don't know this before we try it */
1509  setrlimit (RLIMIT_NOFILE, &r);
1510  }
1511  sk_last = MAX_SOCKETS;
1512 #else
1513  sk_last = SK_FIRST+1;
1514 #endif /* __DJGPP__ */
1515 
1516  sk_list = NULL;
1517  memset (&inuse[0], 0, sizeof(inuse));
1518  memset (&sk_hashes, 0, sizeof(sk_hashes));
1519 
1520  DAEMON_ADD (sock_daemon);
1521 
1522 #if defined(USE_FORTIFY) && defined(USE_DEBUG)
1523  Fortify_EnterScope();
1524  Fortify_SetOutputFunc (bsd_fortify_print);
1525  RUNDOWN_ADD (sock_fortify_exit, 140);
1526 #endif
1527  return (TRUE);
1528 }
1529 
1535 {
1536  Socket *sock;
1537 
1538  if (!init_sockets())
1539  return (NULL);
1540 
1541  for (sock = sock_hash_get(s); sock; sock = sock->next)
1542  if (sock->fd == s)
1543  return (sock);
1544  return (NULL);
1545 }
1546 
1550 static BOOL sock_raw_add (Socket *sock, int family)
1551 {
1552  int i;
1553 
1554 #if defined(USE_IPV6)
1555  if (family == AF_INET6)
1556  {
1557  for (i = 0; i < MAX_RAW6_BUFS; i++)
1558  {
1559  _raw6_Socket *raw6 = SOCK_CALLOC (sizeof(*raw6));
1560 
1561  if (!raw6)
1562  {
1563  if (i == 0) /* Failing to allocate 1 buffer is fatal */
1564  return (FALSE);
1565 
1566  if (i > 0)
1567  break;
1568  }
1569  raw6->ip_type = IP6_TYPE;
1570  raw6->next = sock->raw6_sock;
1571  sock->raw6_sock = raw6;
1572  }
1573  return (TRUE);
1574  }
1575 #endif
1576  if (family == AF_INET)
1577  {
1578  for (i = 0; i < MAX_RAW_BUFS; i++)
1579  {
1580  _raw_Socket *raw = SOCK_CALLOC (sizeof(*raw));
1581 
1582  if (!raw)
1583  {
1584  if (i == 0)
1585  return (FALSE);
1586 
1587  if (i > 0)
1588  break;
1589  }
1590  raw->ip_type = IP4_TYPE;
1591  raw->next = sock->raw_sock;
1592  sock->raw_sock = raw;
1593  }
1594  return (TRUE);
1595  }
1596  return (FALSE);
1597 }
1598 
1602 static Socket *socklist_add (int s, int type, int proto, int family)
1603 {
1604  Socket *sock = SOCK_CALLOC (sizeof(*sock));
1605  void *proto_sk;
1606  BOOL okay;
1607 
1608  if (!sock)
1609  return (NULL);
1610 
1611  switch (proto)
1612  {
1613  case IPPROTO_TCP:
1614  /* Only tcp times out on inactivity
1615  */
1616  sock->timeout = sock_delay;
1617  sock->linger_time = TCP_LINGERTIME;
1618  sock->tcp_sock = SOCK_CALLOC (sizeof(*sock->tcp_sock));
1619  proto_sk = sock->tcp_sock;
1620  if (!sock->tcp_sock)
1621  goto fail;
1622  break;
1623 
1624  case IPPROTO_UDP:
1625  sock->udp_sock = SOCK_CALLOC (sizeof(*sock->udp_sock));
1626  proto_sk = sock->udp_sock;
1627  if (!sock->udp_sock)
1628  goto fail;
1629  break;
1630 
1631  default: /* type == SOCK_RAW/SOCK_PACKET */
1632  proto_sk = NULL;
1633  if (type == SOCK_PACKET)
1634  okay = sock_packet_add (sock);
1635  else okay = sock_raw_add (sock, family);
1636  if (!okay)
1637  goto fail;
1638  break;
1639  }
1640 
1641 #if defined(__DJGPP__) && defined(USE_FSEXT)
1642  if (!__FSEXT_set_data(s,sock))
1643  {
1644  SOCK_FATAL (("%s (%d) Fatal: cannot grow FSEXT table\n",
1645  __FILE__, __LINE__));
1646  goto fail;
1647  }
1648 #else
1649  ARGSUSED (proto_sk);
1650 #endif
1651 
1652  /* Link 'sock' into the 'sk_list'
1653  */
1654  sock->next = sk_list;
1655  sk_list = sock;
1656  sock_hash_add (s, sock);
1657 
1658  sock->fd = s;
1659  sock->so_type = type;
1660  sock->so_proto = proto;
1661  sock->so_family = family;
1662  sock->so_state = SS_UNCONNECTED;
1663  sock->send_lowat = DEFAULT_SEND_LOWAT;
1664  sock->recv_lowat = DEFAULT_RECV_LOWAT;
1665  sock->ip_ttl = IPDEFTTL;
1666  sock->ip_tos = 0;
1667  sock->cookie = SAFETY_TCP;
1668  return (sock);
1669 
1670 fail:
1671  if (proto_sk)
1672  free (proto_sk);
1673  else if (type == SOCK_PACKET)
1674  sock_packet_del (sock);
1675  else
1676  sock_raw_del (sock);
1677 
1678  free (sock);
1679  return (NULL);
1680 }
1681 
1685 static int set_proto (int type, BOOL is_ip6, int *proto)
1686 {
1687 #if defined(USE_IPV6)
1688  if (is_ip6 && !_sock_set_mcast_rx_mode())
1689  {
1690  SOCK_ERRNO (ENETDOWN);
1691  SOCK_DEBUGF (("\nsocket: ENETDOWN; %s", pkt_strerror(_pkt_errno)));
1692  return (-1);
1693  }
1694 #endif
1695 
1696  if (type == SOCK_STREAM)
1697  {
1698  if (*proto == 0)
1699  *proto = IPPROTO_TCP;
1700 
1701  else if (*proto != IPPROTO_TCP)
1702  {
1703  SOCK_ERRNO (EPROTONOSUPPORT);
1704  SOCK_DEBUGF (("\nsocket: invalid STREAM protocol (%d)", *proto));
1705  return (-1);
1706  }
1707  }
1708  else if (type == SOCK_DGRAM)
1709  {
1710  if (*proto == 0)
1711  *proto = IPPROTO_UDP;
1712 
1713  else if (*proto != IPPROTO_UDP)
1714  {
1715  SOCK_ERRNO (EPROTONOSUPPORT);
1716  SOCK_DEBUGF (("\nsocket: invalid DGRAM protocol (%d)", *proto));
1717  return (-1);
1718  }
1719  }
1720  else if (type == SOCK_RAW)
1721  {
1722  if (*proto == IPPROTO_RAW) /* match all IP-protocols */
1723  *proto = IPPROTO_IP;
1724 
1725 #if defined(USE_IPV6)
1726  if (is_ip6)
1727  ip6_raw_hook = sock_raw6_recv; /* hook for _ip6_handler() */
1728  else
1729 #endif
1730  ip4_raw_hook = sock_raw4_recv; /* hook for _ip4_handler() */
1731  }
1732  else if (type == SOCK_PACKET)
1733  {
1734  *proto = 0;
1735  if (!_sock_set_promisc_rx_mode())
1736  {
1737  SOCK_ERRNO (ENETDOWN);
1738  SOCK_DEBUGF (("\nsocket: ENETDOWN; %s", pkt_strerror(_pkt_errno)));
1739  return (-1);
1740  }
1741  }
1742  ARGSUSED (is_ip6);
1743  return (0);
1744 }
1745 
1746 /*
1747  * Return a friendly name for 'proto'.
1748  */
1749 #if defined(USE_DEBUG)
1750 static const char *proto_name (int proto)
1751 {
1752  static const struct search_list proto_names[] = {
1753  { IPPROTO_IP, "IPPROTO_IP" },
1754  { IPPROTO_ICMP, "IPPROTO_ICMP" },
1755  { IPPROTO_IGMP, "IPPROTO_IGMP" },
1756  { IPPROTO_GGP, "IPPROTO_GGP" },
1757  { IPPROTO_IPIP, "IPPROTO_IPIP" },
1758  { IPPROTO_TCP, "IPPROTO_TCP" },
1759  { IPPROTO_EGP, "IPPROTO_EGP" },
1760  { IPPROTO_IGRP, "IPPROTO_IGRP" },
1761  { IPPROTO_PUP, "IPPROTO_PUP" },
1762  { IPPROTO_UDP, "IPPROTO_UDP" },
1763  { IPPROTO_IDP, "IPPROTO_IDP" },
1764  { IPPROTO_TP, "IPPROTO_TP" },
1765  { IPPROTO_XTP, "IPPROTO_XTP" },
1766  { IPPROTO_RSVP, "IPPROTO_RSVP" },
1767  { IPPROTO_ESP, "IPPROTO_ESP" },
1768  { IPPROTO_AH, "IPPROTO_AH" },
1769  { IPPROTO_ICMPV6, "IPPROTO_ICMPV6" },
1770  { IPPROTO_NONE, "IPPROTO_NONE" },
1771  { IPPROTO_EON, "IPPROTO_EON" },
1772  { IPPROTO_ENCAP, "IPPROTO_ENCAP" },
1773  { IPPROTO_PIM, "IPPROTO_PIM" },
1774  { IPPROTO_VRRP, "IPPROTO_VRRP" },
1775  { IPPROTO_SCTP, "IPPROTO_SCTP" },
1776  { IPPROTO_DIVERT, "IPPROTO_DIVERT" },
1777  { IPPROTO_RAW, "IPPROTO_RAW" },
1778  { IPPROTO_MAX, "IPPROTO_MAX" },
1779  };
1780  return list_lookup (proto, proto_names, DIM(proto_names));
1781 }
1782 #endif
1783 
1794 int W32_CALL socket (int family, int type, int protocol)
1795 {
1796  Socket *sock = NULL;
1797  char *err = NULL;
1798  const char *fam;
1799  int s;
1800  BOOL is_ip6;
1801 
1802  if (!init_sockets())
1803  {
1804  SOCK_ERRNO (ENETDOWN);
1805  return (-1);
1806  }
1807 
1808  if (family != AF_UNSPEC &&
1809  family != AF_INET &&
1810  family != AF_PACKET
1811 #if defined(USE_IPV6)
1812  && family != AF_INET6
1813 #endif
1814  )
1815  {
1816  SOCK_DEBUGF (("\nsocket: invalid family (%d)", family));
1817  SOCK_ERRNO (EAFNOSUPPORT);
1818  return (-1);
1819  }
1820 
1821  if (type != SOCK_STREAM &&
1822  type != SOCK_DGRAM &&
1823  type != SOCK_PACKET &&
1824  type != SOCK_RAW)
1825  {
1826  SOCK_DEBUGF (("\nsocket: invalid type (%d)", type));
1827  SOCK_ERRNO (ESOCKTNOSUPPORT);
1828  return (-1);
1829  }
1830 
1831  if (family == AF_PACKET)
1832  {
1833  type = SOCK_PACKET;
1834  family = AF_UNSPEC; /* !! is this correct? */
1835  /* protocol ignored; could be ETH_P_ALL */
1836  }
1837 
1838  if (type == SOCK_RAW && (protocol < IPPROTO_IP || protocol >= IPPROTO_MAX))
1839  {
1840  SOCK_DEBUGF (("\nsocket: invalid SOCK_RAW proto (%d)", protocol));
1841  SOCK_ERRNO (EINVAL);
1842  return (-1);
1843  }
1844 
1845  is_ip6 = (family == AF_INET6);
1846  fam = (is_ip6 ? "6" : "");
1847 
1848  if (set_proto(type, is_ip6, &protocol) < 0)
1849  return (-1);
1850 
1851  s = sock_alloc_fd (&err);
1852  if (s >= 0)
1853  sock = socklist_add (s, type, protocol, family);
1854 
1855  switch (type)
1856  {
1857  case SOCK_STREAM:
1858  SOCK_DEBUGF (("\nsocket: fam:AF_INET%s type:STREAM, proto %s, %d",
1859  fam, proto_name(protocol), s));
1860  break;
1861  case SOCK_DGRAM:
1862  SOCK_DEBUGF (("\nsocket: fam:AF_INET%s type:DGRAM, proto %s, %d",
1863  fam, proto_name(protocol), s));
1864  break;
1865  case SOCK_RAW:
1866  SOCK_DEBUGF (("\nsocket: fam:AF_INET%s type:RAW, proto %s, %d",
1867  fam, proto_name(protocol), s));
1868  break;
1869  case SOCK_PACKET:
1870  SOCK_DEBUGF (("\nsocket: fam:AF_UNSPEC type:PACKET, %d", s));
1871  break;
1872  }
1873 
1874  if (err) /* sock_alloc_fd() failed */
1875  {
1876  SOCK_DEBUGF ((", EMFILE; %s", err));
1877  SOCK_ERRNO (EMFILE);
1878  return (-1);
1879  }
1880 
1881  if (!sock) /* socklist_add() failed */
1882  {
1883  if (s >= 0)
1884  sock_close_fd (s);
1885  SOCK_DEBUGF ((", ENOMEM"));
1886  SOCK_ERRNO (ENOMEM);
1887  return (-1);
1888  }
1889 
1890  if (type == SOCK_PACKET)
1891  {
1892  sock->old_eth_peek = _eth_recv_peek;
1893  _eth_recv_peek = (int (W32_CALL*)(void*)) sock_packet_peek;
1894  }
1895 
1897  ARGSUSED (fam);
1898  return (s);
1899 }
1900 
1912 static int stream_cancel (const _tcp_Socket *tcp, BYTE icmp_type, int error)
1913 {
1914  Socket *socket;
1915  BOOL should_drop = (icmp_type == ICMP_UNREACH &&
1916  tcp->stress >= tcp->rigid) ||
1917  (tcp->ip_type == 0); /* already aborted */
1918 
1919  for (socket = sk_list; socket; socket = socket->next)
1920  if (socket->so_type == SOCK_STREAM &&
1921  tcp == socket->tcp_sock && should_drop)
1922  {
1923  socket->so_state |= SS_CONN_REFUSED;
1924  socket->so_error = error;
1925  return (1);
1926  }
1927  return (0);
1928 }
1929 
1930 static int dgram_cancel (const _udp_Socket *udp, BYTE icmp_type, int error)
1931 {
1932  Socket *socket;
1933  int num = 0;
1934 
1935  for (socket = sk_list; socket; socket = socket->next)
1936  if (socket->so_type == SOCK_DGRAM && udp == socket->udp_sock)
1937  {
1938  socket->so_state |= SS_CONN_REFUSED;
1939  socket->so_error = error;
1940  num++;
1941  }
1942  ARGSUSED (icmp_type);
1943  return (num);
1944 }
1945 
1946 #if defined(USE_DEBUG)
1947 static __inline const char *ip_proto_str (WORD prot)
1948 {
1949  switch (prot)
1950  {
1951  case UDP_PROTO:
1952  return ("UDP");
1953  case TCP_PROTO:
1954  return ("TCP");
1955  case ICMP_PROTO:
1956  return ("ICMP");
1957  case IGMP_PROTO:
1958  return ("IGMP");
1959  default:
1960  return ("unknown");
1961  }
1962 }
1963 #endif
1964 
1965 /*
1966  * Handler for lower layer ICMP messages/errors.
1967  * Return number of BSD-sockets the ICMP-event matched
1968  * (retval not used yet).
1969  */
1970 static int icmp_callback (sock_type *s, BYTE icmp_type, BYTE icmp_code)
1971 {
1972  const char *type_str = "??";
1973  int error;
1974 
1975  if (icmp_type == ICMP_UNREACH)
1976  error = (icmp_code == ICMP_UNREACH_NET ||
1977  icmp_code == ICMP_UNREACH_NET_UNKNOWN ||
1978  icmp_code == ICMP_UNREACH_NET_PROHIB) ?
1979  ENETUNREACH : EHOSTUNREACH;
1980  else error = ECONNREFUSED;
1981 
1982  if (icmp_type < DIM(icmp_type_str))
1983  type_str = icmp_type_str [icmp_type];
1984 
1985  SOCK_DEBUGF (("\n icmp_callback (s=%" ADDR_FMT ", IP-proto %s, %s, code %d)",
1986  ADDR_CAST(s), ip_proto_str(s->udp.ip_type), type_str, icmp_code));
1987 
1988  if (icmp_type == ICMP_UNREACH || icmp_type == ICMP_PARAMPROB)
1989  {
1990  if (s->udp.ip_type == UDP_PROTO)
1991  return dgram_cancel (&s->udp, icmp_type, error);
1992 
1993  if (s->udp.ip_type == TCP_PROTO)
1994  return stream_cancel (&s->tcp, icmp_type, error);
1995  }
1996  ARGSUSED (type_str);
1997  return (0);
1998 }
1999 
2003 int _UDP_open (Socket *socket, struct in_addr host, WORD loc_port, WORD rem_port)
2004 {
2005  DWORD ip = ntohl (host.s_addr);
2006 
2007  loc_port = ntohs (loc_port);
2008  rem_port = ntohs (rem_port);
2009 
2010  if (!udp_open (socket->udp_sock, loc_port, ip, rem_port, NULL))
2011  return (0);
2012 
2013  _sock_set_rcv_buf ((sock_type*)socket->udp_sock, DEFAULT_UDP_SIZE);
2014  socket->udp_sock->icmp_callb = (icmp_upcall) icmp_callback;
2015  return (1);
2016 }
2017 
2018 int _UDP_listen (Socket *socket, struct in_addr host, WORD port)
2019 {
2020  _udp_Socket *udp = socket->udp_sock;
2021  DWORD addr;
2022 
2023  port = ntohs (port);
2024 
2025  if (socket->so_state & SS_PRIV)
2026  {
2027  int size = sizeof(recv_buf) * MAX_DGRAMS;
2028  void *pool = malloc (size);
2029 
2030  if (!pool)
2031  {
2032  SOCK_FATAL (("%s (%d) Fatal: Allocation failed\n",
2033  __FILE__, __LINE__));
2034  SOCK_ERRNO (ENOMEM);
2035  return (-1);
2036  }
2037  socket->bcast_pool = (recv_buf**) pool;
2038  socket->pool_size = size;
2039 
2040  /* Mapping `INADDR_ANY' to `INADDR_BROADCAST' causes udp_demux()
2041  * to demux to the correct watt-socket; s->hisaddr = IP_BCAST_ADDR in
2042  * passive socket demux loop.
2043  */
2044  if (host.s_addr == INADDR_ANY)
2045  addr = INADDR_BROADCAST;
2046  else addr = ntohl (host.s_addr);
2047 
2048  udp_listen (udp, port, addr, 0, NULL);
2049 
2050  /* Setup _recvdaemon() to enqueue broadcast/"unconnected" messages
2051  */
2052  sock_recv_init ((sock_type*)udp, pool, size);
2053  }
2054  else
2055  {
2056  addr = ntohl (host.s_addr);
2057  udp_listen (udp, port, addr, 0, NULL);
2058  }
2059  udp->icmp_callb = (icmp_upcall) icmp_callback;
2060  return (1);
2061 }
2062 
2063 
2067 int _TCP_open (Socket *socket, struct in_addr host, WORD loc_port, WORD rem_port)
2068 {
2069  DWORD dest = ntohl (host.s_addr);
2070 
2071  loc_port = ntohs (loc_port);
2072  rem_port = ntohs (rem_port);
2073 
2074  if (!tcp_open (socket->tcp_sock, loc_port, dest, rem_port, NULL))
2075  return (0);
2076 
2077  if (socket->so_state & SS_NBIO)
2078  socket->tcp_sock->locflags |= LF_NOCLOSE;
2079 
2092  /* Advertise a large rcv-win from the next ACK on.
2093  */
2094  _sock_set_rcv_buf ((sock_type*)socket->tcp_sock, tcp_recv_win);
2095  socket->tcp_sock->icmp_callb = (icmp_upcall) icmp_callback;
2096  return (1);
2097 }
2098 
2099 int _TCP_listen (Socket *socket, struct in_addr host, WORD port)
2100 {
2101  DWORD addr = ntohl (host.s_addr);
2102  WORD loc_port = ntohs (port);
2103 
2104  tcp_listen (socket->tcp_sock, loc_port, addr, 0, NULL, 0);
2105  socket->tcp_sock->icmp_callb = (icmp_upcall) icmp_callback;
2106  return (1);
2107 }
2108 
2109 #if defined(USE_IPV6)
2110 int _TCP6_open (Socket *socket, const void *dst, WORD loc_port, WORD rem_port)
2111 {
2112  _tcp_Socket *tcp = socket->tcp_sock;
2113  UINT rtt;
2114 
2115  SIO_TRACE (("_TCP6_open"));
2116 
2117  WATT_LARGE_CHECK (tcp, sizeof(*tcp));
2118  _tcp_unthread (tcp, FALSE); /* just in case not totally closed */
2119 
2120  memset (tcp, 0, sizeof(*tcp));
2121  tcp->state = tcp_StateCLOSED; /* otherwise is tcp_StateLISTEN on failure */
2122 
2123  if (!_eth_is_init) /* GvB 2002-09, Lets us survive without a working eth */
2124  {
2125  SOCK_ERRNO (ENETDOWN);
2126  tcp->err_msg = _LANG (_eth_not_init);
2127  return (0);
2128  }
2129 
2130  if (IN6_ARE_ADDR_EQUAL(dst,&in6addr_any) || IN6_IS_ADDR_MULTICAST(dst))
2131  {
2132  SOCK_ERRNO (EINVAL);
2133  sprintf (tcp->err_buf, _LANG("Illegal destination (%s)"), _inet6_ntoa(dst));
2134  tcp->err_msg = tcp->err_buf;
2135  return (0);
2136  }
2137 
2138  if (!icmp6_neigh_solic (dst, &tcp->his_ethaddr)) /* This blocks! */
2139  {
2140  SOCK_ERRNO (EHOSTUNREACH);
2141  strcpy (tcp->err_buf, _LANG("Neighbor Solic failed "));
2142  strcat (tcp->err_buf, _inet6_ntoa(dst));
2143  tcp->err_msg = tcp->err_buf;
2144  STAT (ip6stats.ip6s_noroute++);
2145  return (0);
2146  }
2147 
2149 
2150  memcpy (&tcp->my6addr, &in6addr_my_ip, sizeof(tcp->my6addr));
2151  memcpy (&tcp->his6addr, dst, sizeof(tcp->his6addr));
2152 
2153  loc_port = ntohs (loc_port);
2154  rem_port = ntohs (rem_port);
2155 
2156  tcp->is_ip6 = TRUE;
2157  tcp->icmp_callb = (icmp_upcall) icmp_callback;
2158  tcp->state = tcp_StateSYNSENT;
2159  tcp->ip_type = TCP_PROTO;
2160  tcp->max_seg = _mss;
2161  tcp->cwindow = 1;
2162  tcp->wwindow = 0; /* slow start VJ algorithm */
2163  tcp->vj_sa = INIT_VJSA;
2164  tcp->rto = tcp_OPEN_TO; /* added 14-Dec 1999, GV */
2165  tcp->myaddr = my_ip_addr;
2166  tcp->myport = find_free_port (loc_port,1); /* get a nonzero port val */
2167  tcp->locflags = LF_LINGER; /* close via TIMEWT state */
2168  tcp->ttl = _default_ttl;
2169  tcp->hisport = rem_port;
2170  tcp->send_next = INIT_SEQ();
2171  tcp->flags = tcp_FlagSYN;
2172  tcp->unhappy = TRUE;
2173  tcp->protoHandler = NULL;
2174  tcp->usr_yield = NULL;
2175 
2176  tcp->safetysig = SAFETY_TCP; /* marker signatures */
2177  tcp->safetytcp = SAFETY_TCP;
2178  tcp->next = _tcp_allsocs; /* insert into chain */
2179 
2180 /* sock_yield (tcp, tcp6_yield); */
2182  _tcp_allsocs = tcp;
2183 
2186  if (tcp_nagle)
2187  tcp->sockmode = SOCK_MODE_NAGLE;
2188  tcp->sockmode |= SOCK_MODE_BINARY;
2189 
2190  tcp->timeout = set_timeout (tcp_LONGTIMEOUT);
2191 
2192  TCP_SEND (tcp); /* send opening SYN */
2193 
2194  /* find previous RTT replacing RTT set in tcp_send() above
2195  */
2196  if (tcp_rtt_get(tcp, &rtt, NULL))
2197  tcp->rtt_time = set_timeout (rtt);
2198  else tcp->rtt_time = set_timeout (tcp_OPEN_TO);
2199  return (1);
2200 }
2201 
2202 int _TCP6_listen (Socket *socket, const void *host, WORD loc_port)
2203 {
2205  ARGSUSED (socket);
2206  ARGSUSED (host);
2207  ARGSUSED (loc_port);
2208  return (0);
2209 }
2210 
2211 int _UDP6_open (Socket *socket, const void *host, WORD loc_port, WORD rem_port)
2212 {
2214  _sock_set_rcv_buf ((sock_type*)socket->udp_sock, DEFAULT_UDP_SIZE);
2215  socket->udp_sock->icmp_callb = (icmp_upcall) icmp_callback;
2216  ARGSUSED (host);
2217  ARGSUSED (loc_port);
2218  ARGSUSED (rem_port);
2219  return (0);
2220 }
2221 
2222 int _UDP6_listen (Socket *socket, const void *host, WORD port)
2223 {
2225  ARGSUSED (socket);
2226  ARGSUSED (host);
2227  ARGSUSED (port);
2228  return (0);
2229 }
2230 #endif /* USE_IPV6 */
2231 
2232 
2233 #ifdef NOT_USED
2234 
2240 {
2241  if (!s || s->ip_type != TCP_PROTO)
2242  return (0);
2243 
2244  return (s->state >= tcp_StateFINWT1 &&
2245  s->state <= tcp_StateCLOSED);
2246 }
2247 #endif
2248 
2249 #if 0 /* not finished and seldom needed */
2250 
2254 int W32_CALL socketpair (int family, int type, int protocol, int usockvec[2])
2255 {
2256  Socket *sock1, *sock2;
2257  int s1, s2;
2258 
2259  if ((s1 = socket (family, type, protocol)) < 0)
2260  return (-errno);
2261 
2262  sock1 = socklist_find (s1);
2263 
2264  /* Now grab another socket and try to connect the two together.
2265  */
2266  if ((s2 = socket (family, type, protocol)) < 0)
2267  {
2268  int err = -errno;
2269 
2270  close_s (s1);
2271  return (err);
2272  }
2273 
2274  sock2 = socklist_find (s2);
2275 
2276  sock1->conn = sock2;
2277  sock2->conn = sock1;
2278  sock1->so_state = SS_CONNECTED;
2279  sock2->so_state = SS_CONNECTED;
2280 
2281  usockvec[0] = s1;
2282  usockvec[1] = s2;
2283  return (0);
2284 }
2285 #endif
2286 
2287 #endif /* USE_BSD_API */
Definition: wtypes.h:197
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
mac_address _eth_brdcast
Link-layer broadcast address.
Definition: pcsed.c:51
Socket * _sock_del_fd(int fd, const char *file, unsigned line)
Delete the socket from `inuse' array and all memory associated with it.
Definition: socket.c:701
UINT rto
retransmission timeout
Definition: wattcp.h:646
int _sock_chk_sockaddr(Socket *socket, const struct sockaddr *sa, int len)
Check `sockaddr*' passed to bind/connect.
Definition: socket.c:839
static fd_set inuse[NUM_SOCK_FDSETS]
`inuse[]' has a non-zero bit for each socket-descriptor in use.
Definition: socket.c:148
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
static BOOL sock_raw_add(Socket *sock, int family)
Allocate raw?_Socket buffers for a SOCK_RAW socket.
Definition: socket.c:1550
static void * sock_find_tcp(const _tcp_Socket *tcp)
Finds the 'Socket*' associated with tcp-socket '*tcp'.
Definition: socket.c:826
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
int _TCP_open(Socket *socket, struct in_addr host, WORD loc_port, WORD rem_port)
Open and listen routines for SOCK_STREAM at the socket-level.
Definition: socket.c:2067
static int stream_cancel(const _tcp_Socket *tcp, BYTE icmp_type, int error)
Callback handlers for "ICMP Port/Host/Network Unreachable" or "ICMP Parameter Problem" issued by lowe...
Definition: socket.c:1912
int _default_ttl
Definition: ip4_out.c:54
int W32_CALL sock_abort(sock_type *s)
Abort a UDP/TCP/Raw socket.
Definition: pctcp.c:2823
static char get_pkt_type_eth(const eth_Header *eth)
Return correct PACKET_xx type.
Definition: socket.c:535
WORD ip_type
same ofs as for udp/tcp Socket
Definition: wattcp.h:695
int icmp6_neigh_solic(const void *addr, eth_address *eth)
Definition: pcicmp6.c:172
Definition: socket.h:137
void * _sock_calloc(size_t size, const char *file, unsigned line)
Memory allocation; print some info if allocation fails.
Definition: socket.c:99
BYTE W32_CALL _eth_get_hwtype(BYTE *hwtype, BYTE *hwlen)
Fill in hardware address type/length for BOOTP/DHCP packets.
Definition: pcsed.c:751
int _tcp_keepalive(_tcp_Socket *tcp)
TCP keepalive transmission.
Definition: pctcp.c:2698
int pkt_set_rcv_mode(int mode)
Sets the receive mode of the interface.
Definition: pcpkt.c:1955
static __inline Socket * sk_list_del(int s)
Deletes the list element associated with a socket.
Definition: socket.c:284
BOOL used
used flag; packet not read yet
Definition: wattcp.h:696
int W32_CALL _eth_send(WORD len, const void *sock, const char *file, unsigned line)
_eth_send() does the actual transmission once we are complete with filling the buffer.
Definition: pcsed.c:306
BYTE cwindow
Congestion window.
Definition: wattcp.h:639
DWORD tcp_recv_win
RWIN for BSD sockets only.
Definition: pctcp.c:135
static const char * vendor_version(void)
Return version string of current compiler.
Definition: socket.c:1407
Definition: if.h:84
BYTE wwindow
Van Jacobson's algorithm.
Definition: wattcp.h:640
ip6_address his6addr
peer's IPv6 address
Definition: wattcp.h:620
DIRECT + broadcast packets.
Definition: pcpkt.h:111
void _sock_free_rcv_buf(sock_type *s)
Free receive buffer associated with udp/tcp sockets.
Definition: socket.c:267
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
BYTE rx_buf[tcp_MaxBufSize+1]
received data buffer
Definition: wattcp.h:616
DWORD safetytcp
extra magic marker
Definition: wattcp.h:685
static void sock_daemon(void)
A daemon called from tcp_tick().
Definition: socket.c:1256
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
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
ip6_address my6addr
our IPv6 address
Definition: wattcp.h:619
int W32_CALL watt_sock_init(size_t tcp_Sock_size, size_t udp_Sock_size, size_t time_t_size)
Definition: sock_ini.c:749
DWORD W32_CALL set_timeout(DWORD msec)
Return time for when given timeout (msec) expires.
Definition: timer.c:503
Socket * _socklist_find(int s)
Returns a pointer to the Socket structure associated with socket 's'.
Definition: socket.c:1534
static void sock_raw_del(Socket *sock)
Free buffers and hooks used by a SOCK_RAW socket.
Definition: socket.c:424
int _sock_set_rcv_buf(sock_type *s, size_t len)
Setup a bigger receive buffer, the default in Wattcp is only 2k.
Definition: socket.c:252
BOOL _sock_dos_fd(int s)
_sock_dos_fd - Return TRUE if `s' is a valid DOS/Win32 handle.
Definition: socket.c:222
static Socket * sock_find_udp(const _udp_Socket *udp)
Finds the 'Socket' associated with udp-socket 'udp'.
Definition: socket.c:812
int W32_CALL socketpair(int family, int type, int protocol, int usockvec[2])
socketpair() - Create a pair of connected sockets.
Definition: socket.c:2254
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
BYTE _eth_mac_len
Size of a MAC address.
Definition: pcsed.c:54
static Socket * tcp_sock_daemon(Socket *sock)
Called by sock_daemon() to handle SOCK_STREAM sockets.
Definition: socket.c:1169
int _TCP6_open(Socket *socket, const void *dst, WORD loc_port, WORD rem_port)
Definition: socket.c:2110
Definition: ip.h:67
int W32_CALL sock_fastread(sock_type *s, BYTE *buf, int len)
Read a socket with maximum 'len' bytes.
Definition: pctcp.c:2931
int _UDP_open(Socket *socket, struct in_addr host, WORD loc_port, WORD rem_port)
Open and listen routines for SOCK_DGRAM at the socket-level.
Definition: socket.c:2003
Definition: in.h:146
WORD _pktdevclass
Ethernet, Token, FDDI etc.
Definition: pcpkt.c:51
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
BYTE rx_data[MAX_FRAG_SIZE]
room for 1 jumbo IP packet
Definition: wattcp.h:699
DWORD safetysig
magic marker
Definition: wattcp.h:684
int W32_CALL socket(int family, int type, int protocol)
socket().
Definition: socket.c:1794
BOOL _watt_do_exit
exit program when all boot attempts failed
Definition: sock_ini.c:134
int _UDP6_listen(Socket *socket, const void *host, WORD port)
Definition: socket.c:2222
static void *MS_CDECL socket_op_demux(enum BSD_SOCKET_OPS op,...)
The demultiplexer for callback operations called via '_bsd_socket_hook' from functions in the core Wa...
Definition: socket.c:1086
void _sock_crit_start(void)
Start a critical region.
Definition: socket.c:1296
const char *W32_CALL pkt_strerror(int code)
Return textual error representing error-code.
Definition: pcpkt.c:216
void _sock_crit_stop(void)
Mark the end of a critical region.
Definition: socket.c:1306
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.
static __inline BOOL other_raw_socks(const Socket *_this)
Traverse socket-list to find other SOCK_RAW sockets besides '_this'.
Definition: socket.c:352
static int sock_find_fd(const Socket *socket)
Finds the 'fd' associated with pointer 'socket'.
Definition: socket.c:798
int _pkt_errno
error code set in pcpkt.c API
Definition: pcpkt.c:58
BROADCAST + all multicast.
Definition: pcpkt.h:113
static int set_proto(int type, BOOL is_ip6, int *proto)
Select (and check) a suitable protocol for socket-type.
Definition: socket.c:1685
unsigned sock_packet_receive(Socket *sock, void *buf, unsigned len, struct sockaddr *from, size_t *fromlen)
Called from receive.c for AF_PACKET sockets.
Definition: socket.c:601
BOOL _eth_is_init
we are initialised
Definition: pcsed.c:55
BOOL tcp_nagle
Misc TCP values.
Definition: pctcp.c:131
static void sock_fortify_exit(void)
Exit handler for Fortify.
Definition: socket.c:1326
receive all packets on network
Definition: pcpkt.h:114
DWORD my_ip_addr
our IP address
Definition: pctcp.c:70
static BOOL init_sockets(void)
Main initialisation routine for the BSD socket API.
Definition: socket.c:1483
int _UDP6_open(Socket *socket, const void *host, WORD loc_port, WORD rem_port)
Definition: socket.c:2211
static void check_errno_version(void)
Check that .
Definition: socket.c:1457
const char * _inet6_ntoa(const void *ip)
Convert an IPv6-address 'ip' into a string.
Definition: netaddr.c:401
static struct _raw_Socket * find_free_raw_sock(Socket *sock)
Search in sock->raw?_sock list for an unused raw-buffer.
Definition: socket.c:886
int _pkt_rxmode
active receive mode
Definition: pcpkt.c:56
DWORD seq_num
counter for finding oldest pkt
Definition: wattcp.h:697
static __inline BOOL other_tcp_listeners(const Socket *_this)
Traverse socket-list to find other SOCK_STREAM sockets besides '_this' which are also listening...
Definition: socket.c:331
const sock_type * __get_sock_from_s(int s, int proto)
Hack function if user application needs to use Wattcp core functions for BSD sockets.
Definition: socket.c:308
static BOOL sock_packet_add(Socket *sock)
Allocate ringbuffer and rx-buffers for a SOCK_PACKET socket.
Definition: socket.c:463
struct _eth_last_info _eth_last
Sizes and timestamps of last packet recv/sent.
Definition: pcsed.c:68
UINT max_seg
MSS for this connection.
Definition: wattcp.h:658
int _pkt_forced_rxmode
Forced Rx-mode via WATTCP.CFG.
Definition: pcpkt.c:61
static int sock_raw4_recv(const in_Header *ip)
Called from _ip4_handler() via `_bsd_socket_hook'.
Definition: socket.c:925
unsigned tcp_keep_idle
idle time before sending keepalive
Definition: pctcp.c:132
static BOOL mcast_set
Switch back to normal rx-mode (RXMODE_BROADCAST) if no multicasts active and no more IPv6/SOCK_PACKET...
Definition: socket.c:366
_tcp_Socket * _tcp_allsocs
list of tcp-sockets
Definition: pctcp.c:137
static void do_keepalive(Socket *sock)
Handle keepalive on STREAM socket.
Definition: socket.c:1063
static Socket * udp_sock_daemon(Socket *sock)
Called by sock_daemon() for SOCK_DGRAM sockets.
Definition: socket.c:1236
static Socket * socklist_add(int s, int type, int proto, int family)
Adds a new socket to the sk_list.
Definition: socket.c:1602
BOOL W32_CALL chk_timeout(DWORD value)
Check if milli-sec value has expired:
Definition: timer.c:547
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
unsigned tcp_OPEN_TO
TCP timer values.
Definition: pctcp.c:113
DWORD timeout
timer for retrans etc.
Definition: wattcp.h:631
int _TCP6_listen(Socket *socket, const void *host, WORD loc_port)
Definition: socket.c:2202
struct tcp_Socket * next
link to next tcp-socket
Definition: wattcp.h:613
UINT state
tcp connection state
Definition: wattcp.h:622
int _sock_half_open(const _tcp_Socket *s)
_sock_half_open - Return true if peer closed his side.
Definition: socket.c:2239