1 /***********************************************************************/
5 /* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */
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. */
12 /***********************************************************************/
14 /* $Id: sockopt.c 8968 2008-08-01 13:46:08Z xleroy $ */
21 #include "unixsupport.h"
22 #include "socketaddr.h"
25 #define IPPROTO_IPV6 (-1)
28 #define IPV6_V6ONLY (-1)
39 struct socket_option {
44 /* Table of options, indexed by type */
46 static struct socket_option sockopt_bool[] = {
47 { SOL_SOCKET, SO_DEBUG },
48 { SOL_SOCKET, SO_BROADCAST },
49 { SOL_SOCKET, SO_REUSEADDR },
50 { SOL_SOCKET, SO_KEEPALIVE },
51 { SOL_SOCKET, SO_DONTROUTE },
52 { SOL_SOCKET, SO_OOBINLINE },
53 { SOL_SOCKET, SO_ACCEPTCONN },
54 { IPPROTO_TCP, TCP_NODELAY },
55 { IPPROTO_IPV6, IPV6_V6ONLY}
58 static struct socket_option sockopt_int[] = {
59 { SOL_SOCKET, SO_SNDBUF },
60 { SOL_SOCKET, SO_RCVBUF },
61 { SOL_SOCKET, SO_ERROR },
62 { SOL_SOCKET, SO_TYPE },
63 { SOL_SOCKET, SO_RCVLOWAT },
64 { SOL_SOCKET, SO_SNDLOWAT } };
66 static struct socket_option sockopt_linger[] = {
67 { SOL_SOCKET, SO_LINGER }
70 static struct socket_option sockopt_timeval[] = {
71 { SOL_SOCKET, SO_RCVTIMEO },
72 { SOL_SOCKET, SO_SNDTIMEO }
75 static struct socket_option sockopt_unix_error[] = {
76 { SOL_SOCKET, SO_ERROR }
79 static struct socket_option * sockopt_table[] = {
87 static char * getsockopt_fun_name[] = {
95 static char * setsockopt_fun_name[] = {
110 unix_getsockopt_aux(char * name,
111 enum option_type ty, int level, int option,
114 union option_value optval;
115 socklen_param_type optsize;
121 case TYPE_UNIX_ERROR:
122 optsize = sizeof(optval.i); break;
124 optsize = sizeof(optval.lg); break;
126 optsize = sizeof(optval.tv); break;
128 unix_error(EINVAL, name, Nothing);
131 if (getsockopt(Socket_val(socket), level, option,
132 (void *) &optval, &optsize) == -1)
133 uerror(name, Nothing);
138 return Val_int(optval.i);
140 if (optval.lg.l_onoff == 0) {
141 return Val_int(0); /* None */
143 value res = alloc_small(1, 0); /* Some */
144 Field(res, 0) = Val_int(optval.lg.l_linger);
148 return copy_double((double) optval.tv.tv_sec
149 + (double) optval.tv.tv_usec / 1e6);
150 case TYPE_UNIX_ERROR:
152 return Val_int(0); /* None */
155 err = unix_error_of_code(optval.i);
157 res = alloc_small(1, 0); /* Some */
163 unix_error(EINVAL, name, Nothing);
164 return Val_unit; /* Avoid warning */
169 unix_setsockopt_aux(char * name,
170 enum option_type ty, int level, int option,
171 value socket, value val)
173 union option_value optval;
174 socklen_param_type optsize;
180 optsize = sizeof(optval.i);
181 optval.i = Int_val(val);
184 optsize = sizeof(optval.lg);
185 optval.lg.l_onoff = Is_block (val);
186 if (optval.lg.l_onoff)
187 optval.lg.l_linger = Int_val (Field (val, 0));
191 optsize = sizeof(optval.tv);
192 optval.tv.tv_sec = (int) f;
193 optval.tv.tv_usec = (int) (1e6 * (f - optval.tv.tv_sec));
195 case TYPE_UNIX_ERROR:
197 unix_error(EINVAL, name, Nothing);
200 if (setsockopt(Socket_val(socket), level, option,
201 (void *) &optval, optsize) == -1)
202 uerror(name, Nothing);
207 CAMLprim value unix_getsockopt(value vty, value vsocket, value voption)
209 enum option_type ty = Int_val(vty);
210 struct socket_option * opt = &(sockopt_table[ty][Int_val(voption)]);
211 return unix_getsockopt_aux(getsockopt_fun_name[ty],
218 CAMLprim value unix_setsockopt(value vty, value vsocket, value voption,
221 enum option_type ty = Int_val(vty);
222 struct socket_option * opt = &(sockopt_table[ty][Int_val(voption)]);
223 return unix_setsockopt_aux(setsockopt_fun_name[ty],