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