1 /* -*- mode: C; mode: fold; -*- */
2 /*
3  Copyright (C) 2006-2017,2018 John E. Davis
4  *
5  This file is part of the S-Lang Library.
6  *
7  The S-Lang Library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of the
10  License, or (at your option) any later version.
11  *
12  The S-Lang Library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  General Public License for more details.
16  *
17  You should have received a copy of the GNU General Public License
18  along with this library; if not, write to the Free Software
19  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20  USA.
21  */
22 
23 /* This file was derived from the code in SLtcp.c distributed with slsh */
24 
25 /*{{{ Include Files */
26 
27 #define _BSD_SOURCE 1		       /* to get struct ip_mreq */
28 #define _DEFAULT_SOURCE 1
29 #include "config.h"
30 #include <stdio.h>
31 #include <string.h>
32 
33 #include <stdlib.h>
34 #include <unistd.h>
35 
36 #include <errno.h>
37 #include <ctype.h>
38 #include <stdarg.h>
39 
40 #include <setjmp.h>
41 #include <signal.h>
42 
43 #include <sys/types.h>
44 
45 #include <time.h>
46 #ifdef HAVE_SYS_TIME_H
47 # include <sys/time.h>
48 #endif
49 
50 #ifdef HAVE_SOCKET_H
51 # include <socket.h>
52 #endif
53 
54 #ifdef HAVE_SYS_SOCKET_H
55 # include <sys/socket.h>
56 #endif
57 
58 #if defined(__NT__)
59 # include <winsock.h>
60 # define USE_WINSOCK_SLTCP	1
61 #else
62 # if defined(__MINGW32__)
63 #  define Win32_Winsock
64 #  include <windows.h>
65 #  define USE_WINSOCK_SLTCP	1
66 # endif
67 #endif
68 
69 #ifdef USE_WINSOCK_SLTCP
70 # define USE_WINSOCK_SLTCP	1
71 #else
72 # include <netdb.h>
73 #endif
74 
75 #ifdef HAVE_SYS_UN_H
76 # include <sys/un.h>		       /* for AF_UNIX sockets */
77 #endif
78 
79 #ifdef HAVE_NETINET_IN_H
80 # include <netinet/in.h>
81 #endif
82 
83 #ifdef HAVE_ARPA_INET_H
84 # include <arpa/inet.h>
85 #endif
86 
87 #include <slang.h>
88 SLANG_MODULE(socket);
89 
90 #ifndef h_errno
91 extern int h_errno;
92 #endif
93 
94 /*}}}*/
95 
96 static int SocketError = -1;
97 static int SocketHerrnoError = -1;
98 static int Socket_Type_Id = -1;
99 
100 typedef struct Socket_Type Socket_Type;
101 typedef struct
102 {
103    int domain;
104    int (*connect)(Socket_Type *, int);
105    int (*bind)(Socket_Type *, int);
106 #define MAX_ACCEPT_REF_ARGS 4
107    Socket_Type *(*accept)(Socket_Type *, unsigned int, SLang_Ref_Type **);
108    void (*free_socket_data)(Socket_Type *);
109 }
110 Domain_Methods_Type;
111 
112 struct Socket_Type
113 {
114    int fd;			       /* socket descriptor */
115    Domain_Methods_Type *methods;
116    VOID_STAR socket_data;
117    int domain;
118    int type;
119    int protocol;
120 };
121 
122 static Socket_Type *create_socket (int, int, int, int);
123 static void free_socket (Socket_Type *);
124 static int close_socket (int);
125 
126 /*{{{ Generic Routines */
127 
128 static int Module_H_Errno = 0;
129 
herror_to_string(int h)130 static SLFUTURE_CONST char *herror_to_string (int h)
131 {
132 #ifdef HOST_NOT_FOUND
133    if (h == HOST_NOT_FOUND)
134      return "The specified host is unknown";
135 #endif
136 
137 #ifdef NO_ADDRESS
138    if (h == NO_ADDRESS)
139      return "The requested name is valid but does not have an IP address";
140 #endif
141 
142 #ifdef NO_DATA
143    if (h == NO_DATA)
144      return "The requested name is valid but does not have an IP address";
145 #endif
146 
147 #ifdef NO_RECOVERY
148    if (h == NO_RECOVERY)
149      return "A non-recoverable name server error occurred";
150 #endif
151 
152 #ifdef TRY_AGAIN
153    if (h == TRY_AGAIN)
154      return "A temporary error occurred on an authoritative name server.  Try again later";
155 #endif
156 
157    return "Unknown h_error";
158 }
159 
throw_herror(SLFUTURE_CONST char * what,int h)160 static void throw_herror (SLFUTURE_CONST char *what, int h)
161 {
162    Module_H_Errno = h;
163    SLang_verror (SocketHerrnoError, "%s: %s", what, herror_to_string(h));
164 }
165 
throw_errno_error(SLFUTURE_CONST char * what,int e)166 static void throw_errno_error (SLFUTURE_CONST char *what, int e)
167 {
168    SLerrno_set_errno (e);
169    SLang_verror (SocketError, "%s: %s", what, SLerrno_strerror (e));
170 }
171 
perform_connect(int fd,struct sockaddr * addr,unsigned int len,int throw_err)172 static int perform_connect (int fd, struct sockaddr *addr, unsigned int len, int throw_err)
173 {
174    while (-1 == connect (fd, addr, len))
175      {
176 #ifdef EINTR
177 	if (errno == EINTR)
178 	  {
179 	     if (-1 == SLang_handle_interrupt ())
180 	       return -1;
181 	     continue;
182 	  }
183 #endif
184 	/* The manpage indicates EAGAIN will be returned if no free ports exist.
185 	 * So allow the caller to handle that.
186 	 */
187 	if (throw_err)
188 	  throw_errno_error ("connect", errno);
189 	return -1;
190      }
191    return 0;
192 }
193 
perform_bind(int fd,struct sockaddr * addr,unsigned int len)194 static int perform_bind (int fd, struct sockaddr *addr, unsigned int len)
195 {
196    while (-1 == bind (fd, addr, len))
197      {
198 #ifdef EINTR
199 	if (errno == EINTR)
200 	  {
201 	     if (-1 == SLang_handle_interrupt ())
202 	       return -1;
203 	     continue;
204 	  }
205 #endif
206 	/* The manpage indicates EAGAIN will be returned if no free ports exist.
207 	 * So allow the caller to handle that.
208 	 */
209 	throw_errno_error ("bind", errno);
210 	return -1;
211      }
212    return 0;
213 }
214 
perform_accept(Socket_Type * s,struct sockaddr * addr,unsigned int * lenp)215 static Socket_Type *perform_accept (Socket_Type *s, struct sockaddr *addr, unsigned int *lenp)
216 {
217    socklen_t addr_len;
218    Socket_Type *s1;
219    int fd1;
220 
221    addr_len = *lenp;
222    while (-1 == (fd1 = accept (s->fd, addr, &addr_len)))
223      {
224 #ifdef EINTR
225 	if (errno == EINTR)
226 	  {
227 	     if (-1 == SLang_handle_interrupt ())
228 	       return NULL;
229 	     continue;
230 	  }
231 #endif
232 	throw_errno_error ("accept", errno);
233 	return NULL;
234      }
235    *lenp = (unsigned int) addr_len;
236    if (NULL == (s1 = create_socket (fd1, s->domain, s->type, s->protocol)))
237      (void) close_socket (fd1);
238 
239    return s1;
240 }
241 
242 /*}}}*/
243 
244 /* Domain Methods */
245 #if defined(PF_UNIX) && defined(AF_UNIX) /*{{{ */
246 
free_af_unix(Socket_Type * s)247 static void free_af_unix (Socket_Type *s)
248 {
249    char *file = (char *) s->socket_data;
250    if (file == NULL)
251      return;
252 
253    (void) unlink (file);
254    SLang_free_slstring (file);
255    s->socket_data = NULL;
256 }
257 
connect_af_unix(Socket_Type * s,int nargs)258 static int connect_af_unix (Socket_Type *s, int nargs)
259 {
260    struct sockaddr_un addr;
261    char *file;
262 
263    if (nargs != 1)
264      {
265 	SLang_verror (SL_NumArgs_Error, "This socket expects a filename");
266 	return -1;
267      }
268    if (-1 == SLang_pop_slstring (&file))
269      return -1;
270 
271    if (strlen (file) >= sizeof(addr.sun_path))
272      {
273 	SLang_verror (SL_InvalidParm_Error, "filename too long for PF_UNIX socket");
274 	SLang_free_slstring (file);
275 	return -1;
276      }
277 
278    memset ((char *)&addr, 0, sizeof (struct sockaddr_un));
279    addr.sun_family = AF_UNIX;
280    strcpy (addr.sun_path, file);       /* \0 terminated */
281 
282    SLang_free_slstring (file);
283    return perform_connect (s->fd, (struct sockaddr *)&addr, sizeof (addr), 1);
284 }
285 
bind_af_unix(Socket_Type * s,int nargs)286 static int bind_af_unix (Socket_Type *s, int nargs)
287 {
288    struct sockaddr_un addr;
289    char *file;
290 
291    if (nargs != 1)
292      {
293 	SLang_verror (SL_NumArgs_Error, "This socket expects a filename");
294 	return -1;
295      }
296    if (-1 == SLang_pop_slstring (&file))
297      return -1;
298 
299    if (strlen (file) >= sizeof(addr.sun_path))
300      {
301 	SLang_verror (SL_InvalidParm_Error, "filename too long for PF_UNIX socket");
302 	SLang_free_slstring (file);
303 	return -1;
304      }
305 
306    memset ((char *)&addr, 0, sizeof (struct sockaddr_un));
307    addr.sun_family = AF_UNIX;
308    strcpy (addr.sun_path, file);       /* \0 terminated */
309 
310    (void) unlink (file);
311    s->socket_data = (VOID_STAR) file;
312    return perform_bind (s->fd, (struct sockaddr *)&addr, sizeof (addr));
313 }
314 
accept_af_unix(Socket_Type * s,unsigned int nrefs,SLang_Ref_Type ** refs)315 static Socket_Type *accept_af_unix (Socket_Type *s, unsigned int nrefs, SLang_Ref_Type **refs)
316 {
317    struct sockaddr_un addr;
318    Socket_Type *s1;
319    unsigned int addr_len;
320 
321    (void) refs;
322    if (nrefs != 0)
323      {
324 	SLang_verror (SL_NotImplemented_Error, "accept: reference args not supported for PF_UNIX sockets");
325 	return NULL;
326      }
327    addr_len = sizeof (struct sockaddr_un);
328    s1 = perform_accept (s, (struct sockaddr *)&addr, &addr_len);
329    return s1;
330 }
331 
332 #endif
333 /*}}}*/
334 
335 #if defined(PF_INET) && defined(AF_INET) /*{{{*/
pop_host_port(SLFUTURE_CONST char * what,int nargs,char ** hostp,int * portp)336 static int pop_host_port (SLFUTURE_CONST char *what, int nargs, char **hostp, int *portp)
337 {
338    char *host;
339    int port;
340 
341    if (nargs != 2)
342      {
343 	SLang_verror (SL_NumArgs_Error, "%s on an PF_INET socket requires a hostname and portnumber", what);
344 	return -1;
345      }
346 
347    *hostp = NULL;
348    if ((-1 == SLang_pop_int (&port))
349        || (-1 == SLang_pop_slstring (&host)))
350      return -1;
351 
352    *hostp = host;
353    *portp = port;
354    return 0;
355 }
356 
357 typedef struct
358 {
359    int h_addrtype;		       /* AF_INET or AF_INET6 */
360    int h_length;		       /* length of address */
361    unsigned int num;		       /* num elements of h_addr_list */
362    char **h_addr_list;		       /* Array of num of these */
363 }
364 Host_Addr_Info_Type;
365 
free_host_addr_info(Host_Addr_Info_Type * hinfo)366 static void free_host_addr_info (Host_Addr_Info_Type *hinfo)
367 {
368    if (hinfo == NULL)
369      return;
370    if (hinfo->h_addr_list != NULL)
371      SLfree ((char *)hinfo->h_addr_list);
372    SLfree ((char *) hinfo);
373 }
374 
alloc_host_addr_info(unsigned int num,int h_length)375 static Host_Addr_Info_Type *alloc_host_addr_info (unsigned int num, int h_length)
376 {
377    Host_Addr_Info_Type *hinfo;
378    size_t nbytes;
379    char *buf;
380    unsigned int i;
381 
382    hinfo = (Host_Addr_Info_Type *) SLcalloc (1, sizeof (Host_Addr_Info_Type));
383    if (hinfo == NULL)
384      return NULL;
385 
386    /* We need memory to hold num (char *) addresses + num*h_length bytes */
387    nbytes = num * sizeof(char *) + num * h_length;
388    if (NULL == (buf = (char *)SLmalloc (nbytes)))
389      {
390 	SLfree ((char *)hinfo);
391 	return NULL;
392      }
393    hinfo->h_addr_list = (char **)buf;
394    buf += num*sizeof(char *);
395    for (i = 0; i < num; i++)
396      {
397 	hinfo->h_addr_list[i] = buf;
398 	buf += h_length;
399      }
400    hinfo->num = num;
401    hinfo->h_length = h_length;
402 
403    return hinfo;
404 }
405 
406 /* glibc removed the h_addr compat macro, which messes up the logic below. */
407 # ifndef h_addr
408 #  ifdef __GNUC_PREREQ
409 #   if __GNUC_PREREQ(2,8)
410 #    define h_addr "unused"	       /* define it, but do not use it */
411 #   endif
412 #  endif
413 # endif
414 
get_host_addr_info(char * host)415 static Host_Addr_Info_Type *get_host_addr_info (char *host)
416 {
417    in_addr_t addr;
418    Host_Addr_Info_Type *hinfo;
419    struct hostent *hp;
420    unsigned int max_retries;
421 # ifndef h_addr
422    char *fake_h_addr_list[2];
423 # endif
424    char **h_addr_list;
425    unsigned int i, num;
426 
427 # ifndef INADDR_NONE
428 #  define INADDR_NONE ((in_addr_t)(-1))
429 # endif
430    if ((isdigit ((unsigned char)*host))
431        && (INADDR_NONE != (addr = inet_addr (host))))
432      {
433 	/* Numerical address */
434 	if (NULL == (hinfo = alloc_host_addr_info (1, sizeof(in_addr_t))))
435 	  return NULL;
436 	hinfo->h_addrtype = AF_INET;
437 	memcpy (hinfo->h_addr_list[0], (char *)&addr, sizeof(in_addr_t));
438 	return hinfo;
439      }
440 
441    max_retries = 3;
442    while (NULL == (hp = gethostbyname (host)))
443      {
444 # ifdef TRY_AGAIN
445 	max_retries--;
446 	if (max_retries && (h_errno == TRY_AGAIN))
447 	  {
448 	     sleep (1);
449 	     continue;
450 	  }
451 # endif
452 	throw_herror ("gethostbyname", h_errno);
453 	return NULL;
454      }
455 # ifndef h_addr
456    /* Older interface.  There is only one address, so fake a list */
457    h_addr_list = fake_h_addr_list;
458    h_addr_list [0] = hp->h_addr;
459    h_addr_list [1] = NULL;
460 # else
461    h_addr_list = hp->h_addr_list;
462 # endif
463 
464    /* Now count the number of addresses */
465    num = 0;
466    while (h_addr_list[num] != NULL)
467      num++;
468 
469    if (num == 0)
470      {
471 # ifdef NO_DATA
472 	throw_herror ("gethostbyname", NO_DATA);
473 # else
474 	throw_herror ("gethostbyname", NO_ADDRESS);
475 # endif
476 	return NULL;
477      }
478 
479    if (NULL == (hinfo = alloc_host_addr_info (num, hp->h_length)))
480      return NULL;
481 
482    hinfo->h_addrtype = hp->h_addrtype;
483 
484    for (i = 0; i < num; i++)
485      memcpy (hinfo->h_addr_list[i], h_addr_list[i], hp->h_length);
486 
487    return hinfo;
488 }
489 
connect_af_inet(Socket_Type * s,int nargs)490 static int connect_af_inet (Socket_Type *s, int nargs)
491 {
492    struct sockaddr_in s_in;
493    int port;
494    char *host;
495    Host_Addr_Info_Type *hinfo;
496    unsigned int i;
497 
498    if (-1 == pop_host_port ("connect", nargs, &host, &port))
499      return -1;
500 
501    if (NULL == (hinfo = get_host_addr_info (host)))
502      {
503 	SLang_free_slstring (host);
504 	return -1;
505      }
506 
507    if (hinfo->h_addrtype != AF_INET)
508      {
509 # ifdef AF_INET6
510 	if (hinfo->h_addrtype == AF_INET6)
511 	  SLang_verror (SL_NOT_IMPLEMENTED, "AF_INET6 not implemented");
512 	else
513 # endif
514 	  SLang_verror (SocketError, "Unknown socket family for host %s", host);
515 	SLang_free_slstring (host);
516 	free_host_addr_info (hinfo);
517 	return -1;
518      }
519 
520    memset ((char *) &s_in, 0, sizeof(s_in));
521    s_in.sin_family = hinfo->h_addrtype;
522    s_in.sin_port = htons((unsigned short) port);
523 
524    for (i = 0; i < hinfo->num; i++)
525      {
526 	memcpy ((char *) &s_in.sin_addr, hinfo->h_addr_list[i], hinfo->h_length);
527 	if (-1 == perform_connect (s->fd, (struct sockaddr *)&s_in, sizeof (s_in), 0))
528 	  continue;
529 
530 	free_host_addr_info (hinfo);
531 	SLang_free_slstring (host);
532 	return 0;
533      }
534    throw_errno_error ("connect", errno);
535    free_host_addr_info (hinfo);
536    SLang_free_slstring (host);
537    return -1;
538 }
539 
bind_af_inet(Socket_Type * s,int nargs)540 static int bind_af_inet (Socket_Type *s, int nargs)
541 {
542    struct sockaddr_in s_in;
543    char *host;
544    int port;
545    int status;
546    Host_Addr_Info_Type *hinfo;
547 
548    if (-1 == pop_host_port ("connect", nargs, &host, &port))
549      return -1;
550 
551    if (NULL == (hinfo = get_host_addr_info (host)))
552      {
553 	SLang_free_slstring (host);
554 	return -1;
555      }
556 
557    if (hinfo->h_addrtype != AF_INET)
558      {
559 # ifdef AF_INET6
560 	if (hinfo->h_addrtype == AF_INET6)
561 	  SLang_verror (SL_NOT_IMPLEMENTED, "AF_INET6 not implemented");
562 	else
563 # endif
564 	  SLang_verror (SocketError, "Unknown socket family for host %s", host);
565 	SLang_free_slstring (host);
566 	free_host_addr_info (hinfo);
567 	return -1;
568      }
569 
570    memset ((char *) &s_in, 0, sizeof(s_in));
571    s_in.sin_family = hinfo->h_addrtype;
572    s_in.sin_port = htons((unsigned short) port);
573 
574    memcpy ((char *) &s_in.sin_addr, hinfo->h_addr_list[0], hinfo->h_length);
575 
576    status = perform_bind (s->fd, (struct sockaddr *)&s_in, sizeof (s_in));
577 
578    free_host_addr_info (hinfo);
579    SLang_free_slstring (host);
580    return status;
581 }
582 
583 /* Usage: s1 = accept (s [,&host,&port]); */
accept_af_inet(Socket_Type * s,unsigned int nrefs,SLang_Ref_Type ** refs)584 static Socket_Type *accept_af_inet (Socket_Type *s, unsigned int nrefs, SLang_Ref_Type **refs)
585 {
586    struct sockaddr_in s_in;
587    Socket_Type *s1;
588    unsigned int addr_len;
589 
590    if ((nrefs != 0) && (nrefs != 2))
591      {
592 	SLang_verror (SL_NumArgs_Error, "accept (sock [,&host,&port])");
593 	return NULL;
594      }
595 
596    addr_len = sizeof (struct sockaddr_in);
597    s1 = perform_accept (s, (struct sockaddr *)&s_in, &addr_len);
598 
599    if ((s1 == NULL) || (nrefs == 0))
600      return s1;
601 
602    if (nrefs == 2)
603      {
604 	char *host;
605 	char host_ip[32];  /* aaa.bbb.ccc.ddd */
606 	unsigned char *bytes = (unsigned char *)&s_in.sin_addr;
607 	int port = ntohs (s_in.sin_port);
608 	sprintf (host_ip, "%d.%d.%d.%d",
609 		 (int)bytes[0],(int)bytes[1],(int)bytes[2],(int)bytes[3]);
610 
611 	if (NULL == (host = SLang_create_slstring (host_ip)))
612 	  {
613 	     free_socket (s1);
614 	     return NULL;
615 	  }
616 	if (-1 == SLang_assign_to_ref (refs[0], SLANG_STRING_TYPE, (VOID_STAR)&host))
617 	  {
618 	     SLang_free_slstring (host);
619 	     free_socket (s1);
620 	     return NULL;
621 	  }
622 	SLang_free_slstring (host);
623 	if (-1 == SLang_assign_to_ref (refs[1], SLANG_INT_TYPE, &port))
624 	  {
625 	     free_socket (s1);
626 	     return NULL;
627 	  }
628      }
629    return s1;
630 }
631 
632 #endif
633 
634 /*}}}*/
635 
636 static Domain_Methods_Type Domain_Methods_Table [] =
637 {
638 #if defined(PF_UNIX) && defined(AF_UNIX)
639    {PF_UNIX, connect_af_unix, bind_af_unix, accept_af_unix, free_af_unix},
640 #endif
641 #if defined(PF_INET) && defined(AF_INET)
642    {PF_INET, connect_af_inet, bind_af_inet, accept_af_inet, NULL},
643 #endif
644    {0, NULL, NULL, NULL, NULL}
645 };
646 
lookup_domain_methods(int domain)647 static Domain_Methods_Type *lookup_domain_methods (int domain)
648 {
649    Domain_Methods_Type *a = Domain_Methods_Table;
650    unsigned int i, n;
651 
652    n = sizeof (Domain_Methods_Table)/sizeof(Domain_Methods_Type);
653    for (i = 0; i < n; i++)
654      {
655 	if (a->domain == domain)
656 	  return a;
657 	a++;
658      }
659 
660    SLang_verror (SocketError, "Unsupported socket domain: %d", domain);
661    return NULL;
662 }
663 
close_socket(int fd)664 static int close_socket (int fd)
665 {
666    /* Do not call close again to avoid undefined behavior */
667    if (-1 == close (fd))
668      {
669 #ifdef EINTR
670 	if (errno == EINTR)
671 	  {
672 	     if (-1 == SLang_handle_interrupt ())
673 	       return -1;
674 	  }
675 #endif
676 	return -1;
677      }
678    return 0;
679 }
680 
free_socket(Socket_Type * s)681 static void free_socket (Socket_Type *s)
682 {
683    if (s == NULL)
684      return;
685 
686    if ((s->methods != NULL) && (s->methods->free_socket_data != NULL))
687      (*s->methods->free_socket_data)(s);
688 
689    if (s->fd != -1)
690      close_socket (s->fd);
691 
692    SLfree ((char *) s);
693 }
694 
create_socket(int fd,int domain,int type,int protocol)695 static Socket_Type *create_socket (int fd, int domain, int type, int protocol)
696 {
697    Socket_Type *s;
698    Domain_Methods_Type *methods;
699 
700    if (NULL == (methods = lookup_domain_methods (domain)))
701      return NULL;
702 
703    s = (Socket_Type *)SLmalloc (sizeof (Socket_Type));
704    if (s == NULL)
705      return s;
706    memset ((char *)s, 0, sizeof (Socket_Type));
707 
708    s->fd = fd;
709    s->domain = domain;
710    s->protocol = protocol;
711    s->type = type;
712    s->methods = methods;
713 
714    return s;
715 }
716 
close_socket_callback(VOID_STAR cd)717 static int close_socket_callback (VOID_STAR cd)
718 {
719    Socket_Type *s;
720 
721    s = (Socket_Type *) cd;
722    if (s->fd == -1)
723      {
724 #ifdef EBADF
725 	errno = EBADF;
726 #endif
727 	return -1;
728      }
729    if (-1 == close (s->fd))
730      return -1;
731 
732    s->fd = -1;
733    return 0;
734 }
735 
free_socket_callback(VOID_STAR cd)736 static void free_socket_callback (VOID_STAR cd)
737 {
738    free_socket ((Socket_Type *)cd);
739 }
740 
socket_to_fd(Socket_Type * s)741 static SLFile_FD_Type *socket_to_fd (Socket_Type *s)
742 {
743    SLFile_FD_Type *f;
744    if (NULL == (f = SLfile_create_fd ("*socket*", s->fd)))
745      return NULL;
746 
747    (void) SLfile_set_clientdata (f, free_socket_callback, (VOID_STAR)s, Socket_Type_Id);
748    (void) SLfile_set_close_method (f, close_socket_callback);
749    return f;
750 }
751 
socket_from_fd(SLFile_FD_Type * f)752 static Socket_Type *socket_from_fd (SLFile_FD_Type *f)
753 {
754    Socket_Type *s;
755    if (-1 == SLfile_get_clientdata (f, Socket_Type_Id, (VOID_STAR *)&s))
756      {
757 	SLang_verror (SL_TypeMismatch_Error, "File descriptor does not represent a socket");
758 	return NULL;
759      }
760    return s;
761 }
762 
763 /* This function frees the socket before returning */
push_socket(Socket_Type * s)764 static int push_socket (Socket_Type *s)
765 {
766    SLFile_FD_Type *f;
767    int status;
768 
769    if (s == NULL)
770      return SLang_push_null ();
771 
772    if (NULL == (f = socket_to_fd (s)))
773      {
774 	free_socket (s);
775 	return -1;
776      }
777 
778    status = SLfile_push_fd (f);
779    SLfile_free_fd (f);
780    return status;
781 }
782 
pop_socket(SLFile_FD_Type ** fp)783 static Socket_Type *pop_socket (SLFile_FD_Type **fp)
784 {
785    SLFile_FD_Type *f;
786    Socket_Type *s;
787 
788    if (-1 == SLfile_pop_fd (&f))
789      {
790 	*fp = NULL;
791 	return NULL;
792      }
793    if (NULL == (s = socket_from_fd (f)))
794      {
795 	SLfile_free_fd (f);
796 	return NULL;
797      }
798    *fp = f;
799    return s;
800 }
801 
socket_intrin(int * domain,int * type,int * protocol)802 static void socket_intrin (int *domain, int *type, int *protocol)
803 {
804    Socket_Type *s;
805    int fd;
806 
807    if (NULL == lookup_domain_methods (*domain))
808      return;
809 
810    fd = socket (*domain, *type, *protocol);
811    if (fd == -1)
812      {
813 	throw_errno_error ("socket", errno);
814 	return;
815      }
816 
817    if (NULL == (s = create_socket (fd, *domain, *type, *protocol)))
818      {
819 	close_socket (fd);
820 	return;
821      }
822 
823    (void) push_socket (s);	       /* frees it upon error */
824    return;
825 }
826 
827 #ifdef HAVE_SOCKETPAIR
socketpair_intrin(int * domain,int * type,int * protocol)828 static void socketpair_intrin (int *domain, int *type, int *protocol)
829 {
830    Socket_Type *s;
831    int fds[2];
832 
833    if (NULL == lookup_domain_methods (*domain))
834      return;
835 
836    if (-1 == socketpair (*domain, *type, *protocol, fds))
837      {
838 	throw_errno_error ("socketpair", errno);
839 	return;
840      }
841 
842    if (NULL == (s = create_socket (fds[0], *domain, *type, *protocol)))
843      {
844 	close_socket (fds[0]);
845 	close_socket (fds[1]);
846 	return;
847      }
848    if (-1 == push_socket (s))	       /* frees upon error */
849      {
850 	close_socket (fds[1]);
851 	return;
852      }
853    if (NULL == (s = create_socket (fds[1], *domain, *type, *protocol)))
854      {
855 	close_socket (fds[1]);
856 	return;
857      }
858    (void) push_socket (s);	       /* frees it upon error */
859    return;
860 }
861 #endif
862 
connect_intrin(void)863 static void connect_intrin (void)
864 {
865    Socket_Type *s;
866    SLFile_FD_Type *f;
867    int nargs = SLang_Num_Function_Args;
868    Domain_Methods_Type *methods;
869 
870    if (-1 == SLroll_stack (-nargs))
871      return;
872 
873    if (NULL == (s = pop_socket (&f)))
874      return;
875    nargs--;
876 
877    methods = s->methods;
878    (void) (*methods->connect)(s, nargs);
879    SLfile_free_fd (f);
880 }
881 
bind_intrin(void)882 static void bind_intrin (void)
883 {
884    Socket_Type *s;
885    SLFile_FD_Type *f;
886    int nargs = SLang_Num_Function_Args;
887    Domain_Methods_Type *methods;
888 
889    if (-1 == SLroll_stack (-nargs))
890      return;
891 
892    if (NULL == (s = pop_socket (&f)))
893      return;
894    nargs--;
895 
896    methods = s->methods;
897    (void)(*methods->bind)(s, nargs);
898    SLfile_free_fd (f);
899 }
900 
listen_intrin(SLFile_FD_Type * f,int * np)901 static void listen_intrin (SLFile_FD_Type *f, int *np)
902 {
903    Socket_Type *s;
904 
905    if (NULL == (s = socket_from_fd (f)))
906      return;
907 
908    if (0 == listen (s->fd, *np))
909      return;
910 
911    throw_errno_error ("listen", errno);
912 }
913 
accept_intrin(void)914 static void accept_intrin (void)
915 {
916    SLFile_FD_Type *f;
917    Socket_Type *s, *s1;
918    Domain_Methods_Type *methods;
919    int nargs = SLang_Num_Function_Args;
920    SLang_Ref_Type *refs[MAX_ACCEPT_REF_ARGS];
921    int i;
922 
923    if (nargs <= 0)
924      {
925 	SLang_verror (SL_Usage_Error, "s1 = accept (s [,&v...])");
926 	return;
927      }
928 
929    if (-1 == SLroll_stack (-nargs))
930      return;
931 
932    if (NULL == (s = pop_socket (&f)))
933      return;
934    nargs--;
935 
936    if (nargs > MAX_ACCEPT_REF_ARGS)
937      {
938 	SLang_verror (SL_NumArgs_Error, "accept: too many reference args");
939 	SLfile_free_fd (f);
940      }
941    memset ((char *)refs, 0, sizeof (refs));
942 
943    i = nargs;
944    while (i != 0)
945      {
946 	i--;
947 	if (-1 == SLang_pop_ref (refs+i))
948 	  goto free_return;
949      }
950 
951    methods = s->methods;
952    if (NULL != (s1 = (*methods->accept)(s, nargs, refs)))
953      (void) push_socket (s1);	       /* frees it upon error */
954 
955    /* drop */
956 
957 free_return:
958    for (i = 0; i < nargs; i++)
959      {
960 	if (refs[i] != NULL)
961 	  SLang_free_ref (refs[i]);
962      }
963    SLfile_free_fd (f);
964 }
965 
966 typedef struct
967 {
968    int optname;
969    int (*setopt)(Socket_Type *, int, int);
970    int (*getopt)(Socket_Type *, int, int);
971 }
972 SockOpt_Type;
973 
do_setsockopt(int fd,int level,int optname,void * val,socklen_t len)974 static int do_setsockopt (int fd, int level, int optname, void *val, socklen_t len)
975 {
976    if (-1 == setsockopt (fd, level, optname, val, len))
977      {
978 	throw_errno_error ("setsockopt", errno);
979 	return -1;
980      }
981    return 0;
982 }
983 
do_getsockopt(int fd,int level,int optname,void * val,socklen_t * lenp)984 static int do_getsockopt (int fd, int level, int optname, void *val, socklen_t *lenp)
985 {
986    if (-1 == getsockopt (fd, level, optname, val, lenp))
987      {
988 	throw_errno_error ("getsockopt", errno);
989 	return -1;
990      }
991    return 0;
992 }
993 
set_int_sockopt(Socket_Type * s,int level,int optname)994 static int set_int_sockopt (Socket_Type *s, int level, int optname)
995 {
996    int val;
997 
998    if (-1 == SLang_pop_int (&val))
999      return -1;
1000 
1001    return do_setsockopt (s->fd, level, optname, (void *)&val, sizeof(int));
1002 }
1003 
get_int_sockopt(Socket_Type * s,int level,int optname)1004 static int get_int_sockopt (Socket_Type *s, int level, int optname)
1005 {
1006    int val;
1007    socklen_t len;
1008 
1009    len = sizeof (int);
1010    if (-1 == do_getsockopt (s->fd, level, optname, (void *)&val, &len))
1011      return -1;
1012 
1013    return SLang_push_int (val);
1014 }
1015 
set_str_sockopt(Socket_Type * s,int level,int optname)1016 static int set_str_sockopt (Socket_Type *s, int level, int optname)
1017 {
1018    char *val;
1019    socklen_t len;
1020    int ret;
1021 
1022    if (-1 == SLang_pop_slstring (&val))
1023      return -1;
1024    len = strlen (val); len++;
1025    ret = do_setsockopt (s->fd, level, optname, (void *)val, len);
1026    SLang_free_slstring (val);
1027    return ret;
1028 }
get_str_sockopt(Socket_Type * s,int level,int optname)1029 static int get_str_sockopt (Socket_Type *s, int level, int optname)
1030 {
1031    char buf[1024];
1032    socklen_t len = sizeof (buf)-1;
1033 
1034    if (-1 == do_getsockopt (s->fd, level, optname, (void *)buf, &len))
1035      return -1;
1036 
1037    buf[len] = 0;
1038    return SLang_push_string (buf);
1039 }
1040 
set_struct_sockopt(Socket_Type * s,int level,int optname,SLang_CStruct_Field_Type * cs,VOID_STAR v,socklen_t len)1041 static int set_struct_sockopt (Socket_Type *s, int level, int optname,
1042 			       SLang_CStruct_Field_Type *cs, VOID_STAR v,
1043 			       socklen_t len)
1044 {
1045    int ret;
1046 
1047    if (-1 == SLang_pop_cstruct (v, cs))
1048      return -1;
1049 
1050    ret = do_setsockopt (s->fd, level, optname, v, len);
1051    SLang_free_cstruct (v, cs);
1052    return ret;
1053 }
1054 
get_struct_sockopt(Socket_Type * s,int level,int optname,SLang_CStruct_Field_Type * cs,VOID_STAR v,socklen_t len)1055 static int get_struct_sockopt (Socket_Type *s, int level, int optname,
1056 			       SLang_CStruct_Field_Type *cs, VOID_STAR v,
1057 			       socklen_t len)
1058 {
1059    if (-1 == do_getsockopt (s->fd, level, optname, v, &len))
1060      return -1;
1061 
1062    return SLang_push_cstruct (v, cs);
1063 }
1064 
1065 static SLang_CStruct_Field_Type TV_Struct [] =
1066 {
1067    MAKE_CSTRUCT_INT_FIELD(struct timeval, tv_sec, "tv_sec", 0),
1068    MAKE_CSTRUCT_INT_FIELD(struct timeval, tv_sec, "tv_usec", 0),
1069    SLANG_END_CSTRUCT_TABLE
1070 };
1071 
set_timeval_sockopt(Socket_Type * s,int level,int optname)1072 static int set_timeval_sockopt (Socket_Type *s, int level, int optname)
1073 {
1074    struct timeval tv;
1075    return set_struct_sockopt (s, level, optname, TV_Struct, (VOID_STAR)&tv, sizeof(struct timeval));
1076 }
1077 
get_timeval_sockopt(Socket_Type * s,int level,int optname)1078 static int get_timeval_sockopt (Socket_Type *s, int level, int optname)
1079 {
1080    struct timeval tv;
1081    return get_struct_sockopt (s, level, optname, TV_Struct, (VOID_STAR)&tv, sizeof(struct timeval));
1082 }
1083 
1084 #if defined(SO_LINGER)
1085 static SLang_CStruct_Field_Type Linger_Struct [] =
1086 {
1087    MAKE_CSTRUCT_INT_FIELD(struct linger, l_onoff, "l_onoff", 0),
1088    MAKE_CSTRUCT_INT_FIELD(struct linger, l_linger, "l_linger", 0),
1089    SLANG_END_CSTRUCT_TABLE
1090 };
1091 
set_linger_sockopt(Socket_Type * s,int level,int optname)1092 static int set_linger_sockopt (Socket_Type *s, int level, int optname)
1093 {
1094    struct linger lg;
1095    return set_struct_sockopt (s, level, optname, Linger_Struct, (VOID_STAR)&lg, sizeof(struct linger));
1096 }
1097 
get_linger_sockopt(Socket_Type * s,int level,int optname)1098 static int get_linger_sockopt (Socket_Type *s, int level, int optname)
1099 {
1100    struct linger lg;
1101    return get_struct_sockopt (s, level, optname, Linger_Struct, (VOID_STAR)&lg, sizeof(struct linger));
1102 }
1103 #endif
1104 
1105 #ifdef SOL_SOCKET
1106 static SockOpt_Type SO_Option_Table[] =
1107 {
1108 # ifdef SO_KEEPALIVE
1109    {SO_KEEPALIVE, set_int_sockopt, get_int_sockopt},
1110 # endif
1111 # ifdef SO_OOBINLINE
1112    {SO_OOBINLINE, set_int_sockopt, get_int_sockopt},
1113 # endif
1114 # ifdef SO_RCVLOWAT
1115    {SO_RCVLOWAT, set_int_sockopt, get_int_sockopt},
1116 # endif
1117 # ifdef SO_SNDLOWAT
1118    {SO_SNDLOWAT, set_int_sockopt, get_int_sockopt},
1119 # endif
1120 # ifdef SO_BSDCOMPAT
1121    {SO_BSDCOMPAT, set_int_sockopt, get_int_sockopt},
1122 # endif
1123 # ifdef SO_PASSCRED
1124    {SO_PASSCRED, set_int_sockopt, get_int_sockopt},
1125 # endif
1126 # ifdef SO_BINDTODEVICE
1127    {SO_BINDTODEVICE, set_str_sockopt, get_str_sockopt},
1128 # endif
1129 # ifdef SO_DEBUG
1130    {SO_DEBUG, set_int_sockopt, get_int_sockopt},
1131 # endif
1132 # ifdef SO_REUSEADDR
1133    {SO_REUSEADDR, set_int_sockopt, get_int_sockopt},
1134 # endif
1135 # ifdef SO_TYPE
1136    {SO_TYPE, set_int_sockopt, get_int_sockopt},
1137 # endif
1138 # ifdef SO_ACCEPTCONN
1139    {SO_ACCEPTCONN, set_int_sockopt, get_int_sockopt},
1140 # endif
1141 # ifdef SO_DONTROUTE
1142    {SO_DONTROUTE, set_int_sockopt, get_int_sockopt},
1143 # endif
1144 # ifdef SO_BROADCAST
1145    {SO_BROADCAST, set_int_sockopt, get_int_sockopt},
1146 # endif
1147 # ifdef SO_SNDBUF
1148    {SO_SNDBUF, set_int_sockopt, get_int_sockopt},
1149 # endif
1150 # ifdef SO_RCVBUF
1151    {SO_RCVBUF, set_int_sockopt, get_int_sockopt},
1152 # endif
1153 # ifdef SO_PRIORITY
1154    {SO_PRIORITY, set_int_sockopt, get_int_sockopt},
1155 # endif
1156 # ifdef SO_ERROR
1157    {SO_ERROR, NULL, get_int_sockopt},
1158 # endif
1159 # ifdef SO_PEERCRED
1160    /* {SO_PEERCRED, NULL, get_peercred_sockopt}, */
1161 # endif
1162 # ifdef SO_RCVTIMEO
1163    {SO_RCVTIMEO, set_timeval_sockopt, get_timeval_sockopt},
1164 # endif
1165 # ifdef SO_SNDTIMEO
1166    {SO_SNDTIMEO, set_timeval_sockopt, get_timeval_sockopt},
1167 # endif
1168 # ifdef SO_LINGER
1169    {SO_LINGER, set_linger_sockopt, get_linger_sockopt},
1170 # endif
1171 
1172    {-1, NULL, NULL}
1173 };
1174 #endif				       /* SOL_SOCKET */
1175 
1176 #if defined(IP_ADD_MEMBERSHIP) /* either add or drop same args */
set_multicast_sockopt(Socket_Type * s,int level,int option)1177 static int set_multicast_sockopt (Socket_Type *s, int level, int option)
1178 {
1179    struct ip_mreq group;
1180    char *multi;
1181    char *local = NULL;
1182    Host_Addr_Info_Type *multi_info = NULL;
1183    Host_Addr_Info_Type *local_info = NULL;
1184    int ret = -1;
1185 
1186    if (-1 == SLang_pop_slstring(&multi))
1187      return -1;
1188 
1189    if (5 == SLang_Num_Function_Args)
1190      {
1191 	if (-1 == SLang_pop_slstring(&local))
1192 	  {
1193 	     SLang_free_slstring (multi);
1194 	     return -1;
1195 	  }
1196      }
1197 
1198    if (NULL == (multi_info = get_host_addr_info (multi)))
1199      goto free_and_return;
1200 
1201    if (local != NULL)
1202      {
1203 	if (NULL == (local_info = get_host_addr_info (local)))
1204 	  goto free_and_return;
1205 
1206 	memcpy ((char *) &group.imr_interface.s_addr, local_info->h_addr_list[0], local_info->h_length);
1207      }
1208    else
1209      {
1210 	group.imr_interface.s_addr = INADDR_ANY;
1211      }
1212    memcpy ((char *) &group.imr_multiaddr.s_addr, multi_info->h_addr_list[0], multi_info->h_length);
1213 
1214    ret = do_setsockopt (s->fd, level, option, (void *)&group, sizeof(group));
1215 
1216 free_and_return:
1217 
1218    SLang_free_slstring(multi);
1219    if (NULL != local)
1220      SLang_free_slstring(local);
1221    free_host_addr_info (multi_info);
1222    if (NULL != local_info)
1223      free_host_addr_info (local_info);
1224 
1225    return ret;
1226 }
1227 #endif
1228 
1229 #if defined(IP_MULTICAST_IF)
set_multicast_if_sockopt(Socket_Type * s,int level,int option)1230 static int set_multicast_if_sockopt (Socket_Type *s, int level, int option)
1231 {
1232    struct in_addr iface;
1233    char *local;
1234    Host_Addr_Info_Type *local_info;
1235 
1236    if (-1 == SLang_pop_slstring(&local))
1237      return -1;
1238 
1239    if (NULL == (local_info = get_host_addr_info (local)))
1240      {
1241 	SLang_free_slstring (local);
1242 	return -1;
1243      }
1244    memcpy ((char *) &iface.s_addr, local_info->h_addr_list[0], local_info->h_length);
1245 
1246    SLang_free_slstring(local);
1247    free_host_addr_info (local_info);
1248 
1249    return do_setsockopt (s->fd, level, option, (void *)&iface, sizeof(iface));
1250 }
1251 #endif
1252 
1253 #ifdef SOL_IP
1254 static SockOpt_Type IP_Option_Table[] =
1255 {
1256 # ifdef IP_OPTIONS
1257    /* {IP_OPTIONS, NULL, NULL}, */
1258 # endif
1259 # ifdef IP_PKTINFO
1260    /* {IP_PKTINFO, NULL, NULL}, */
1261 # endif
1262 # ifdef IP_RECVTOS
1263    /* {IP_RECVTOS, NULL, NULL}, */
1264 # endif
1265 # ifdef IP_RECVTTL
1266    /* {IP_RECVTTL, NULL, NULL}, */
1267 # endif
1268 # ifdef IP_RECVOPTS
1269    /* {IP_RECVOPTS, NULL, NULL}, */
1270 # endif
1271 # ifdef IP_TOS
1272    /* {IP_TOS, set_int_sockopt, get_int_sockopt}, */
1273 # endif
1274 # ifdef IP_TTL
1275    {IP_TTL, set_int_sockopt, get_int_sockopt},
1276 # endif
1277 # ifdef IP_HDRINCL
1278    {IP_HDRINCL, set_int_sockopt, get_int_sockopt},
1279 # endif
1280 # ifdef IP_RECVERR
1281    /* {IP_RECVERR, set_int_sockopt, get_int_sockopt}, */
1282 # endif
1283 # ifdef IP_MTU_DISCOVER
1284    /* {IP_MTU_DISCOVER, set_int_sockopt, get_int_sockopt}, */
1285 # endif
1286 # ifdef IP_MTU
1287    {IP_MTU_DISCOVER, NULL, get_int_sockopt},
1288 # endif
1289 # ifdef IP_ROUTER_ALERT
1290    {IP_ROUTER_ALERT, set_int_sockopt, get_int_sockopt},
1291 # endif
1292 # ifdef IP_MULTICAST_TTL
1293    {IP_MULTICAST_TTL, set_int_sockopt, get_int_sockopt},
1294 # endif
1295 # ifdef IP_MULTICAST_LOOP
1296    {IP_MULTICAST_LOOP, set_int_sockopt, get_int_sockopt},
1297 # endif
1298 # ifdef IP_ADD_MEMBERSHIP
1299    {IP_ADD_MEMBERSHIP, set_multicast_sockopt, NULL},
1300 # endif
1301 # ifdef IP_DROP_MEMBERSHIP
1302    {IP_DROP_MEMBERSHIP, set_multicast_sockopt, NULL},
1303 # endif
1304 # ifdef IP_MULTICAST_IF
1305    {IP_MULTICAST_IF, set_multicast_if_sockopt, NULL},
1306 # endif
1307 
1308    {-1, NULL, NULL}
1309 };
1310 #endif				       /* SOL_IP */
1311 /* Usage: get/setsockopt (socket, level, optname, value) */
getset_sockopt(int set)1312 static void getset_sockopt (int set)
1313 {
1314    Socket_Type *s;
1315    SLFile_FD_Type *f;
1316    int level, optname;
1317    SockOpt_Type *table;
1318 
1319    if (-1 == SLreverse_stack (SLang_Num_Function_Args))
1320      return;
1321 
1322    if (NULL == (s = pop_socket (&f)))
1323      return;
1324 
1325    if ((-1 == SLang_pop_int (&level))
1326        || (-1 == SLang_pop_int (&optname)))
1327      {
1328 	SLfile_free_fd (f);
1329 	return;
1330      }
1331 
1332    switch (level)
1333      {
1334 #ifdef SOL_SOCKET
1335       case SOL_SOCKET: table = SO_Option_Table; break;
1336 #endif
1337 #ifdef SOL_IP
1338       case SOL_IP: table = IP_Option_Table; break;
1339 #endif
1340       default:
1341 	SLang_verror (SL_NotImplemented_Error, "get/setsockopt level %d is not supported", level);
1342 	goto free_return;
1343      }
1344 
1345    while (1)
1346      {
1347 	if (table->optname == optname)
1348 	  {
1349 	     int (*func)(Socket_Type *, int, int);
1350 	     if (set)
1351 	       func = table->setopt;
1352 	     else
1353 	       func = table->getopt;
1354 	     if (func == NULL)
1355 	       goto not_implemented_error;
1356 
1357 	     (void)(*func)(s, level, optname);
1358 	     break;
1359 	  }
1360 	if (table->optname == -1)
1361 	  goto free_return;
1362 
1363 	table++;
1364      }
1365 
1366    /* drop */
1367 free_return:
1368    SLfile_free_fd (f);
1369    return;
1370 
1371 not_implemented_error:
1372    SLang_verror (SL_NotImplemented_Error, "get/setsockopt option %d is not supported at level %d", optname, level);
1373    SLfile_free_fd (f);
1374 }
1375 
setsockopt_intrin(void)1376 static void setsockopt_intrin (void)
1377 {
1378    getset_sockopt (1);
1379 }
getsockopt_intrin(void)1380 static void getsockopt_intrin (void)
1381 {
1382    getset_sockopt (0);
1383 }
1384 
1385 #define I SLANG_INT_TYPE
1386 #define V SLANG_VOID_TYPE
1387 #define F SLANG_FILE_FD_TYPE
1388 static SLang_Intrin_Fun_Type Module_Intrinsics [] =
1389 {
1390    MAKE_INTRINSIC_3("socket", socket_intrin, V, I, I, I),
1391 #ifdef HAVE_SOCKETPAIR
1392    MAKE_INTRINSIC_3("socketpair", socketpair_intrin, V, I, I, I),
1393 #endif
1394    MAKE_INTRINSIC_0("connect", connect_intrin, V),
1395    MAKE_INTRINSIC_0("bind", bind_intrin, V),
1396    MAKE_INTRINSIC_2("listen", listen_intrin, V, F, I),
1397    MAKE_INTRINSIC_0("accept", accept_intrin, V),
1398    MAKE_INTRINSIC_0("getsockopt", getsockopt_intrin, V),
1399    MAKE_INTRINSIC_0("setsockopt", setsockopt_intrin, V),
1400    SLANG_END_INTRIN_FUN_TABLE
1401 };
1402 #undef F
1403 #undef V
1404 #undef I
1405 
1406 static SLang_IConstant_Type Module_IConstants [] =
1407 {
1408 #ifdef SOCK_STREAM
1409    MAKE_ICONSTANT("SOCK_STREAM", SOCK_STREAM),
1410 #endif
1411 #ifdef SOCK_DGRAM
1412    MAKE_ICONSTANT("SOCK_DGRAM", SOCK_DGRAM),
1413 #endif
1414 #ifdef SOCK_RAW
1415    MAKE_ICONSTANT("SOCK_RAW", SOCK_RAW),
1416 #endif
1417 #ifdef SOCK_RDM
1418    MAKE_ICONSTANT("SOCK_RDM", SOCK_RDM),
1419 #endif
1420 #ifdef SOCK_SEQPACKET
1421    MAKE_ICONSTANT("SOCK_SEQPACKET", SOCK_SEQPACKET),
1422 #endif
1423 #ifdef SOCK_PACKET
1424    MAKE_ICONSTANT("SOCK_PACKET", SOCK_PACKET),
1425 #endif
1426 
1427    /* Domains  */
1428 #ifdef PF_UNIX
1429    MAKE_ICONSTANT("PF_UNIX", PF_UNIX),
1430 #endif
1431 #ifdef PF_INET
1432    MAKE_ICONSTANT("PF_INET", PF_INET),
1433 #endif
1434 #ifdef AF_UNIX
1435    MAKE_ICONSTANT("AF_UNIX", AF_UNIX),
1436 #endif
1437 #ifdef AF_INET
1438    MAKE_ICONSTANT("AF_INET", AF_INET),
1439 #endif
1440 
1441 #ifdef SOL_SOCKET
1442    MAKE_ICONSTANT("SOL_SOCKET", SOL_SOCKET),
1443 # ifdef SO_KEEPALIVE
1444    MAKE_ICONSTANT("SO_KEEPALIVE", SO_KEEPALIVE),
1445 # endif
1446 # ifdef SO_OOBINLINE
1447    MAKE_ICONSTANT("SO_OOBINLINE", SO_OOBINLINE),
1448 # endif
1449 # ifdef SO_RCVLOWAT
1450    MAKE_ICONSTANT("SO_RCVLOWAT", SO_RCVLOWAT),
1451 # endif
1452 # ifdef SO_SNDLOWAT
1453    MAKE_ICONSTANT("SO_SNDLOWAT", SO_SNDLOWAT),
1454 # endif
1455 # ifdef SO_BSDCOMPAT
1456    MAKE_ICONSTANT("SO_BSDCOMPAT", SO_BSDCOMPAT),
1457 # endif
1458 # ifdef SO_PASSCRED
1459    MAKE_ICONSTANT("SO_PASSCRED", SO_PASSCRED),
1460 # endif
1461 # ifdef SO_BINDTODEVICE
1462    MAKE_ICONSTANT("SO_BINDTODEVICE", SO_BINDTODEVICE),
1463 # endif
1464 # ifdef SO_DEBUG
1465    MAKE_ICONSTANT("SO_DEBUG", SO_DEBUG),
1466 # endif
1467 # ifdef SO_REUSEADDR
1468    MAKE_ICONSTANT("SO_REUSEADDR", SO_REUSEADDR),
1469 # endif
1470 # ifdef SO_TYPE
1471    MAKE_ICONSTANT("SO_TYPE", SO_TYPE),
1472 # endif
1473 # ifdef SO_ACCEPTCONN
1474    MAKE_ICONSTANT("SO_ACCEPTCONN", SO_ACCEPTCONN),
1475 # endif
1476 # ifdef SO_DONTROUTE
1477    MAKE_ICONSTANT("SO_DONTROUTE", SO_DONTROUTE),
1478 # endif
1479 # ifdef SO_BROADCAST
1480    MAKE_ICONSTANT("SO_BROADCAST", SO_BROADCAST),
1481 # endif
1482 # ifdef SO_SNDBUF
1483    MAKE_ICONSTANT("SO_SNDBUF", SO_SNDBUF),
1484 # endif
1485 # ifdef SO_RCVBUF
1486    MAKE_ICONSTANT("SO_RCVBUF", SO_RCVBUF),
1487 # endif
1488 # ifdef SO_PRIORITY
1489    MAKE_ICONSTANT("SO_PRIORITY", SO_PRIORITY),
1490 # endif
1491 # ifdef SO_ERROR
1492    MAKE_ICONSTANT("SO_ERROR", SO_ERROR),
1493 # endif
1494 # ifdef SO_PEERCRED
1495    MAKE_ICONSTANT("SO_PEERCRED", SO_PEERCRED),
1496 # endif
1497 # ifdef SO_RCVTIMEO
1498    MAKE_ICONSTANT("SO_RCVTIMEO", SO_RCVTIMEO),
1499 # endif
1500 # ifdef SO_SNDTIMEO
1501    MAKE_ICONSTANT("SO_SNDTIMEO", SO_SNDTIMEO),
1502 # endif
1503 # ifdef SO_LINGER
1504    MAKE_ICONSTANT("SO_LINGER", SO_LINGER),
1505 # endif
1506 #endif   			       /* SOL_SOCKET */
1507 
1508 #ifdef SOL_IP
1509    MAKE_ICONSTANT("SOL_IP", SOL_IP),
1510 # ifdef IP_RECVTTL
1511    MAKE_ICONSTANT("IP_RECVTTL", IP_RECVTTL),
1512 # endif
1513 # ifdef IP_RECVOPTS
1514    MAKE_ICONSTANT("IP_RECVOPTS", IP_RECVOPTS),
1515 # endif
1516 # ifdef IP_RECVOPTS
1517    MAKE_ICONSTANT("IP_RECVOPTS", IP_RECVOPTS),
1518 # endif
1519 # ifdef IP_TOS
1520    MAKE_ICONSTANT("IP_TOS", IP_TOS),
1521 # endif
1522 # ifdef IP_TTL
1523    MAKE_ICONSTANT("IP_TTL", IP_TTL),
1524 # endif
1525 # ifdef IP_HDRINCL
1526    MAKE_ICONSTANT("IP_HDRINCL", IP_HDRINCL),
1527 # endif
1528 # ifdef IP_RECVERR
1529    MAKE_ICONSTANT("IP_RECVERR", IP_RECVERR),
1530 # endif
1531 # ifdef IP_MTU_DISCOVER
1532    MAKE_ICONSTANT("IP_MTU_DISCOVER", IP_MTU_DISCOVER),
1533 # endif
1534 # ifdef IP_ROUTER_ALERT
1535    MAKE_ICONSTANT("IP_ROUTER_ALERT", IP_ROUTER_ALERT),
1536 # endif
1537 # ifdef IP_MULTICAST_TTL
1538    MAKE_ICONSTANT("IP_MULTICAST_TTL", IP_MULTICAST_TTL),
1539 # endif
1540 # ifdef IP_MULTICAST_LOOP
1541    MAKE_ICONSTANT("IP_MULTICAST_LOOP", IP_MULTICAST_LOOP),
1542 # endif
1543 # ifdef IP_ADD_MEMBERSHIP
1544    MAKE_ICONSTANT("IP_ADD_MEMBERSHIP", IP_ADD_MEMBERSHIP),
1545 # endif
1546 # ifdef IP_DROP_MEMBERSHIP
1547    MAKE_ICONSTANT("IP_DROP_MEMBERSHIP", IP_DROP_MEMBERSHIP),
1548 # endif
1549 # ifdef IP_MULTICAST_IF
1550    MAKE_ICONSTANT("IP_MULTICAST_IF", IP_MULTICAST_IF),
1551 # endif
1552 # ifdef IP_OPTIONS
1553    MAKE_ICONSTANT("IP_OPTIONS", IP_OPTIONS),
1554 # endif
1555 # ifdef IP_PKTINFO
1556    MAKE_ICONSTANT("IP_PKTINFO", IP_PKTINFO),
1557 # endif
1558 # ifdef IP_RECVTOS
1559    MAKE_ICONSTANT("IP_RECVTOS", IP_RECVTOS),
1560 # endif
1561 # ifdef IPPROTO_IP
1562    MAKE_ICONSTANT("IPPROTO_IP", IPPROTO_IP),
1563 # endif
1564 #endif				       /* SOL_IP */
1565 
1566    SLANG_END_ICONST_TABLE
1567 };
1568 
init_socket_module_ns(char * ns_name)1569 int init_socket_module_ns (char *ns_name)
1570 {
1571    SLang_NameSpace_Type *ns;
1572 
1573    if (SocketError == -1)
1574      {
1575 	if (-1 == (SocketError = SLerr_new_exception (SL_RunTime_Error, "SocketError", "Socket Error")))
1576 	  return -1;
1577 	if (-1 == (SocketHerrnoError = SLerr_new_exception (SocketError, "SocketHError", "Socket h_errno Error")))
1578 	  return -1;
1579      }
1580    if (Socket_Type_Id == -1)
1581      {
1582 	(void) SLfile_create_clientdata_id (&Socket_Type_Id);
1583      }
1584 
1585    if (NULL == (ns = SLns_create_namespace (ns_name)))
1586      return -1;
1587 
1588    if ((-1 == SLns_add_intrin_fun_table (ns, Module_Intrinsics, NULL))
1589        || (-1 == SLns_add_iconstant_table (ns, Module_IConstants, NULL)))
1590      return -1;
1591 
1592    if (-1 == SLns_add_intrinsic_variable(ns, "h_errno", (VOID_STAR)&Module_H_Errno, SLANG_INT_TYPE, 1))
1593      return -1;
1594 
1595    return 0;
1596 }
1597 
deinit_socket_module(void)1598 void deinit_socket_module (void)
1599 {
1600 }
1601