1 /*
2 * Copyright (c) 2011, 2012, 2013
3 * Inferno Nettverk A/S, Norway. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. The above copyright notice, this list of conditions and the following
9 * disclaimer must appear in all copies of the software, derivative works
10 * or modified versions, and any portions thereof, aswell as in all
11 * supporting documentation.
12 * 2. All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 * This product includes software developed by
15 * Inferno Nettverk A/S, Norway.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Inferno Nettverk A/S requests users of this software to return to
31 *
32 * Software Distribution Coordinator or sdc@inet.no
33 * Inferno Nettverk A/S
34 * Oslo Research Park
35 * Gaustadall�en 21
36 * NO-0349 Oslo
37 * Norway
38 *
39 * any improvements or extensions that they make and grant Inferno Nettverk A/S
40 * the rights to redistribute these changes.
41 *
42 */
43
44 #include "common.h"
45
46 #include "qos.h"
47
48 static const char rcsid[] =
49 "$Id: sockopt.c,v 1.26 2013/10/25 12:55:01 karls Exp $";
50
51 struct option {
52 int level;
53 int optname;
54 char *optstr;
55 };
56 static const struct option option[];
57 static const sockopt_t sockopts[];
58 static const sockoptvalsym_t sockoptvalsyms[];
59
60
61 int
socketoptdup(s,new_s)62 socketoptdup(s, new_s)
63 int s;
64 int new_s;
65 {
66 const char *function = "socketoptdup()";
67 unsigned int i;
68 int flags, errno_s;
69 socklen_t len;
70 socketoptvalue_t val;
71
72 errno_s = errno;
73
74 slog(LOG_DEBUG, "%s: fd %d, fd %d", function, s, new_s);
75
76 if (new_s == -1) {
77 struct sockaddr_storage addr;
78 int domain;
79
80 len = sizeof(addr);
81 if (getsockname(s, TOSA(&addr), &len) == -1) {
82 swarn("%s: getsockname(2) failed" , function);
83 return -1;
84 }
85
86 domain = addr.ss_family;
87
88 len = sizeof(val.int_val);
89 if (getsockopt(s, SOL_SOCKET, SO_TYPE, &val, &len) == -1) {
90 swarn("%s: getsockopt(SO_TYPE) failed", function);
91 return -1;
92 }
93
94 if ((new_s = socket(domain, val.int_val, 0)) == -1) {
95 swarn("%s: socket(%d, %d)", function, domain, val.int_val);
96 return -1;
97 }
98 }
99
100 for (i = 0; i < HAVE_DUPSOCKOPT_MAX; ++i) {
101 len = sizeof(val);
102 if (getsockopt(s, option[i].level, option[i].optname, &val, &len) == -1) {
103 if (errno != ENOPROTOOPT)
104 slog(LOG_DEBUG, "%s: getsockopt(%d, %d) failed: %s",
105 function, option[i].level, option[i].optname, strerror(errno));
106
107 continue;
108 }
109
110 if (setsockopt(new_s, option[i].level, option[i].optname, &val, len)
111 == -1)
112 if (errno != ENOPROTOOPT)
113 slog(LOG_DEBUG, "%s: setsockopt(%d, %d) failed: %s",
114 function, option[i].level, option[i].optname, strerror(errno));
115 }
116
117 if ((flags = fcntl(s, F_GETFL, 0)) == -1
118 || fcntl(new_s, F_SETFL, flags) == -1)
119 swarn("%s: fcntl(F_GETFL/F_SETFL)", function);
120
121 errno = errno_s;
122 return new_s;
123 }
124
125 #if DEBUG
126 void
printsocketopts(s)127 printsocketopts(s)
128 const int s;
129 {
130 const char *function = "printsocketopts()";
131 unsigned int i;
132 int flags, errno_s;
133 socklen_t len;
134 socketoptvalue_t val;
135
136 errno_s = errno;
137
138 len = sizeof(val);
139 if (getsockopt(s, SOL_SOCKET, SO_TYPE, &val, &len) == -1) {
140 swarn("%s: getsockopt(SO_TYPE)", function);
141 return;
142 }
143
144 for (i = 0; i < HAVE_DUPSOCKOPT_MAX; ++i) {
145 len = sizeof(val);
146 if (getsockopt(s, option[i].level, option[i].optname, &val, &len) == -1) {
147 if (errno != ENOPROTOOPT)
148 swarn("%s: getsockopt(%s) failed", function, option[i].optstr);
149
150 continue;
151 }
152
153 slog(LOG_DEBUG, "%s: value of socket option \"%s\" is %d\n",
154 function, option[i].optstr, val.int_val);
155 }
156
157 if ((flags = fcntl(s, F_GETFL, 0)) == -1)
158 swarn("%s: fcntl(F_GETFL)", function);
159 else
160 slog(LOG_DEBUG, "%s: value of file status flags: %d\n", function, flags);
161
162 if ((flags = fcntl(s, F_GETFD, 0)) == -1)
163 swarn("fcntl(F_GETFD)");
164 else
165 slog(LOG_DEBUG, "%s: value of file descriptor flags: %d\n",
166 function, flags);
167
168 errno = errno_s;
169 }
170
171 #endif /* DEBUG */
172
173 void
sockopts_dump(void)174 sockopts_dump(void)
175 {
176 const char *function = "sockopts_dump()";
177 int i;
178
179 slog(LOG_DEBUG, "%s: socket option name (level/value) (%d entries):",
180 function, HAVE_SOCKOPTVAL_MAX);
181
182 for (i = 0; i < HAVE_SOCKOPTVAL_MAX; i++)
183 slog(LOG_DEBUG, "%s: %02d: %s (%d/%d)",
184 function, i, sockopts[i].name, sockopts[i].level, sockopts[i].value);
185
186 slog(LOG_DEBUG, "%s: socket option symbolic values (%d entries):",
187 function, HAVE_SOCKOPTVALSYM_MAX);
188
189 for (i = 0; i < HAVE_SOCKOPTVALSYM_MAX; i++) {
190 const sockopt_t *opt;
191
192 SASSERTX(sockoptvalsyms[i].optid < HAVE_SOCKOPTVAL_MAX);
193
194 opt = &sockopts[sockoptvalsyms[i].optid];
195
196 slog(LOG_DEBUG, "%s: %02d: %s: %s (%s)",
197 function,
198 i,
199 opt->name,
200 sockoptvalsyms[i].name,
201 sockoptval2string(sockoptvalsyms[i].symval, opt->opttype, NULL, 0));
202 }
203 }
204
205 const sockopt_t *
optname2sockopt(char * name)206 optname2sockopt(char *name)
207 {
208 int i;
209
210 for (i = 0; i < HAVE_SOCKOPTVAL_MAX; i++) {
211 if (strcmp(name, sockopts[i].name) == 0)
212 return &sockopts[i];
213 }
214
215 return NULL;
216 }
217
218 const sockopt_t *
optval2sockopt(int level,int value)219 optval2sockopt(int level, int value)
220 {
221 int i;
222
223 for (i = 0; i < HAVE_SOCKOPTVAL_MAX; i++) {
224 if (level == sockopts[i].level && value == sockopts[i].value)
225 return &sockopts[i];
226 }
227
228 return NULL;
229 }
230
231 const sockopt_t *
optid2sockopt(size_t optid)232 optid2sockopt(size_t optid)
233 {
234 SASSERTX(optid < HAVE_SOCKOPTVAL_MAX);
235
236 return &sockopts[optid];
237 }
238
239 const sockoptvalsym_t *
optval2valsym(size_t optid,char * name)240 optval2valsym(size_t optid, char *name)
241 {
242 int i;
243
244 for (i = 0; i < HAVE_SOCKOPTVALSYM_MAX; i++) {
245 if (optid == sockoptvalsyms[i].optid
246 && strcmp(name, sockoptvalsyms[i].name) == 0)
247 return &sockoptvalsyms[i];
248 }
249
250 return NULL;
251 }
252
253 /*
254 * Include platform dependent socket option code.
255 */
256 #include "sockopt_gen.c"
257