Sys.Signals module for a Variant type of signals (and a set_signal function that...
[ocaml.git] / otherlibs / unix / socketaddr.c
blob0ee1cf5ee19a7479858e50aa2c488bbbbcc6e40e
1 /***********************************************************************/
2 /* */
3 /* Objective Caml */
4 /* */
5 /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */
6 /* */
7 /* Copyright 1996 Institut National de Recherche en Informatique et */
8 /* en Automatique. All rights reserved. This file is distributed */
9 /* under the terms of the GNU Library General Public License, with */
10 /* the special exception on linking described in file ../../LICENSE. */
11 /* */
12 /***********************************************************************/
14 /* $Id$ */
16 #include <string.h>
17 #include <mlvalues.h>
18 #include <alloc.h>
19 #include <memory.h>
20 #include <errno.h>
21 #include "unixsupport.h"
23 #ifdef HAS_SOCKETS
25 #include "socketaddr.h"
27 #ifdef _WIN32
28 #define EAFNOSUPPORT WSAEAFNOSUPPORT
29 #endif
31 CAMLexport value alloc_inet_addr(struct in_addr * a)
33 value res;
34 /* Use a string rather than an abstract block so that it can be
35 marshaled safely. Remember that a is in network byte order,
36 hence is marshaled in an endian-independent manner. */
37 res = alloc_string(4);
38 memcpy(String_val(res), a, 4);
39 return res;
42 #ifdef HAS_IPV6
44 CAMLexport value alloc_inet6_addr(struct in6_addr * a)
46 value res;
47 res = alloc_string(16);
48 memcpy(String_val(res), a, 16);
49 return res;
52 #endif
54 void get_sockaddr(value mladr,
55 union sock_addr_union * adr /*out*/,
56 socklen_param_type * adr_len /*out*/)
58 switch(Tag_val(mladr)) {
59 #ifndef _WIN32
60 case 0: /* ADDR_UNIX */
61 { value path;
62 mlsize_t len;
63 path = Field(mladr, 0);
64 len = string_length(path);
65 adr->s_unix.sun_family = AF_UNIX;
66 if (len >= sizeof(adr->s_unix.sun_path)) {
67 unix_error(ENAMETOOLONG, "", path);
69 memmove (adr->s_unix.sun_path, String_val(path), len + 1);
70 *adr_len =
71 ((char *)&(adr->s_unix.sun_path) - (char *)&(adr->s_unix))
72 + len;
73 break;
75 #endif
76 case 1: /* ADDR_INET */
77 #ifdef HAS_IPV6
78 if (string_length(Field(mladr, 0)) == 16) {
79 memset(&adr->s_inet6, 0, sizeof(struct sockaddr_in6));
80 adr->s_inet6.sin6_family = AF_INET6;
81 adr->s_inet6.sin6_addr = GET_INET6_ADDR(Field(mladr, 0));
82 adr->s_inet6.sin6_port = htons(Int_val(Field(mladr, 1)));
83 *adr_len = sizeof(struct sockaddr_in6);
84 break;
86 #endif
87 memset(&adr->s_inet, 0, sizeof(struct sockaddr_in));
88 adr->s_inet.sin_family = AF_INET;
89 adr->s_inet.sin_addr = GET_INET_ADDR(Field(mladr, 0));
90 adr->s_inet.sin_port = htons(Int_val(Field(mladr, 1)));
91 *adr_len = sizeof(struct sockaddr_in);
92 break;
96 value alloc_sockaddr(union sock_addr_union * adr /*in*/,
97 socklen_param_type adr_len, int close_on_error)
99 value res;
100 switch(adr->s_gen.sa_family) {
101 #ifndef _WIN32
102 case AF_UNIX:
103 { value n = copy_string(adr->s_unix.sun_path);
104 Begin_root (n);
105 res = alloc_small(1, 0);
106 Field(res,0) = n;
107 End_roots();
108 break;
110 #endif
111 case AF_INET:
112 { value a = alloc_inet_addr(&adr->s_inet.sin_addr);
113 Begin_root (a);
114 res = alloc_small(2, 1);
115 Field(res,0) = a;
116 Field(res,1) = Val_int(ntohs(adr->s_inet.sin_port));
117 End_roots();
118 break;
120 #ifdef HAS_IPV6
121 case AF_INET6:
122 { value a = alloc_inet6_addr(&adr->s_inet6.sin6_addr);
123 Begin_root (a);
124 res = alloc_small(2, 1);
125 Field(res,0) = a;
126 Field(res,1) = Val_int(ntohs(adr->s_inet6.sin6_port));
127 End_roots();
128 break;
130 #endif
131 default:
132 if (close_on_error != -1) close (close_on_error);
133 unix_error(EAFNOSUPPORT, "", Nothing);
135 return res;
138 #endif