Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 475 lines (365 sloc) 11.128 kB
970e51d @msantos Bump version to 0.6.0 and copyright heartbeat
authored
1 /* Copyright (c) 2010-2015, Michael Santos <michael.santos@gmail.com>
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
2 * All rights reserved.
c025a3d @msantos Whitespace cleanup
authored
3 *
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
c025a3d @msantos Whitespace cleanup
authored
7 *
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
8 * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
c025a3d @msantos Whitespace cleanup
authored
10 *
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
11 * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
c025a3d @msantos Whitespace cleanup
authored
14 *
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
15 * Neither the name of the author nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
c025a3d @msantos Whitespace cleanup
authored
18 *
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32 #include "procket.h"
33 #include "ancillary.h"
34
35
53ffa00 @msantos procket_cmd: increase backlog to SOMAXCONN
authored
36 #define BACKLOG 128 /* default backlog for TCP connections */
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
37
f9d88e0 @msantos cleanup: move some checks to separate functions
authored
38 int procket_open_fd(PROCKET_STATE *ps);
39 int procket_check_devname(char *dev, size_t len);
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
40 int procket_pipe(PROCKET_STATE *ps);
96f8a1e @msantos Allow arbitrary socket family, type and protocol
authored
41 int procket_open_socket(PROCKET_STATE *ps);
36d9ec6 @msantos Only look up addresses for TCP and UDP sockets
authored
42 int procket_create_socket(PROCKET_STATE *ps);
43 int procket_lookup_socket(PROCKET_STATE *ps);
bd91116 @msantos Allow setuid open of any character device
authored
44 int procket_open_dev(PROCKET_STATE *ps);
45 int procket_open_char_dev(char *dev);
d4c76dd @msantos Consistent return values from procket executable
authored
46 void error_result(PROCKET_STATE *ps, int err);
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
47 void usage(PROCKET_STATE *ep);
48
f9d88e0 @msantos cleanup: move some checks to separate functions
authored
49 enum {
50 PROCKET_FD_SOCKET,
51 PROCKET_FD_CHARDEV
52 };
53
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
54
55 int
56 main(int argc, char *argv[])
57 {
58 PROCKET_STATE *ps = NULL;
59 int ch = 0;
60
61
d4c76dd @msantos Consistent return values from procket executable
authored
62 ps = calloc(1, sizeof(PROCKET_STATE));
63
64 if (ps == NULL)
65 error_result(ps, errno);
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
66
96f8a1e @msantos Allow arbitrary socket family, type and protocol
authored
67 ps->backlog = BACKLOG;
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
68
721f6a5 @msantos Support IPv6 sockets
authored
69 ps->family = PF_UNSPEC; /* bind IPv4 and IPv6 socket */
96f8a1e @msantos Allow arbitrary socket family, type and protocol
authored
70 ps->type = SOCK_STREAM;
71 ps->protocol = IPPROTO_TCP;
72
f9d88e0 @msantos cleanup: move some checks to separate functions
authored
73 ps->fdtype = PROCKET_FD_SOCKET;
74
721f6a5 @msantos Support IPv6 sockets
authored
75 while ( (ch = getopt(argc, argv, "b:d:F:hI:p:P:T:u:v")) != -1) {
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
76 switch (ch) {
96f8a1e @msantos Allow arbitrary socket family, type and protocol
authored
77 case 'b': /* listen backlog */
78 ps->backlog = atoi(optarg);
79 break;
80 case 'F': /* socket family/domain */
81 ps->family = atoi(optarg);
82 break;
721f6a5 @msantos Support IPv6 sockets
authored
83 case 'u': /* path to Unix socket */
d4c76dd @msantos Consistent return values from procket executable
authored
84 ps->path = strdup(optarg);
85
86 if (ps->path == NULL)
87 error_result(ps, errno);
88
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
89 if (strlen(ps->path) >= UNIX_PATH_MAX)
2b00d6f @msantos Keep port number as a char pointer
authored
90 error_result(ps, ENAMETOOLONG);
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
91 break;
721f6a5 @msantos Support IPv6 sockets
authored
92 case 'p': /* port */
2b00d6f @msantos Keep port number as a char pointer
authored
93 ps->port = strdup(optarg);
94
95 if (ps->port == NULL)
96 error_result(ps, errno);
97
98 if (strlen(ps->port) >= NI_MAXSERV)
99 error_result(ps, ENAMETOOLONG);
721f6a5 @msantos Support IPv6 sockets
authored
100 break;
96f8a1e @msantos Allow arbitrary socket family, type and protocol
authored
101 case 'P': /* socket protocol */
102 ps->protocol = atoi(optarg);
103 break;
104 case 'T': /* socket type */
105 ps->type = atoi(optarg);
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
106 break;
2b00d6f @msantos Keep port number as a char pointer
authored
107 case 'I': /* Interface name */
d4c76dd @msantos Consistent return values from procket executable
authored
108 ps->ifname = strdup(optarg);
109
110 if (ps->ifname == NULL)
111 error_result(ps, errno);
2b00d6f @msantos Keep port number as a char pointer
authored
112
0bf7c2f @msantos And fix the pasto too
authored
113 if (strlen(ps->ifname) >= IFNAMSIZ)
2b00d6f @msantos Keep port number as a char pointer
authored
114 error_result(ps, ENAMETOOLONG);
eba4ec3 Added option to bind a socket to a specific interface
klaar authored
115 break;
2b00d6f @msantos Keep port number as a char pointer
authored
116 case 'd': /* Open a character device */
d4c76dd @msantos Consistent return values from procket executable
authored
117 ps->dev = strdup(optarg);
118
119 if (ps->dev == NULL)
120 error_result(ps, errno);
bd91116 @msantos Allow setuid open of any character device
authored
121
f9d88e0 @msantos cleanup: move some checks to separate functions
authored
122 if (procket_check_devname(ps->dev, 32) < 0)
bd91116 @msantos Allow setuid open of any character device
authored
123 usage(ps);
124
f9d88e0 @msantos cleanup: move some checks to separate functions
authored
125 ps->fdtype = PROCKET_FD_CHARDEV;
dd34004 @msantos Initial support for BPF on BSDs
authored
126 break;
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
127 case 'v':
128 ps->verbose++;
129 break;
130 case 'h':
131 default:
132 usage(ps);
133 }
134 }
135
136 argc -= optind;
137 argv += optind;
138
96f8a1e @msantos Allow arbitrary socket family, type and protocol
authored
139 if (ps->path == NULL)
2b00d6f @msantos Keep port number as a char pointer
authored
140 error_result(ps, ENOENT);
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
141
d4c76dd @msantos Consistent return values from procket executable
authored
142 if (argc > 0) {
143 ps->address = strdup(argv[0]);
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
144
d4c76dd @msantos Consistent return values from procket executable
authored
145 if (ps->address == NULL)
146 error_result(ps, errno);
2b00d6f @msantos Keep port number as a char pointer
authored
147
148 if (strlen(ps->address) >= NI_MAXHOST)
149 error_result(ps, ENAMETOOLONG);
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
150 }
151
d4c76dd @msantos Consistent return values from procket executable
authored
152 if (procket_open_fd(ps) < 0)
153 error_result(ps, errno);
154
155 if ( (setgid(getgid()) < 0) || (setuid(getuid()) < 0))
156 error_result(ps, errno);
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
157
d4c76dd @msantos Consistent return values from procket executable
authored
158 if (procket_pipe(ps) < 0)
159 error_result(ps, errno);
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
160
d4c76dd @msantos Consistent return values from procket executable
authored
161 exit(0);
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
162 }
163
164
f9d88e0 @msantos cleanup: move some checks to separate functions
authored
165 int
166 procket_open_fd(PROCKET_STATE *ps)
167 {
168 switch (ps->fdtype) {
169 case PROCKET_FD_SOCKET:
721f6a5 @msantos Support IPv6 sockets
authored
170 return procket_open_socket(ps);
f9d88e0 @msantos cleanup: move some checks to separate functions
authored
171
172 case PROCKET_FD_CHARDEV:
721f6a5 @msantos Support IPv6 sockets
authored
173 return procket_open_dev(ps);
f9d88e0 @msantos cleanup: move some checks to separate functions
authored
174
721f6a5 @msantos Support IPv6 sockets
authored
175 default:
176 return -1;
177 }
f9d88e0 @msantos cleanup: move some checks to separate functions
authored
178 }
179
180
181 int
182 procket_check_devname(char *dev, size_t len)
183 {
184 char *p = NULL;
185
721f6a5 @msantos Support IPv6 sockets
authored
186
f9d88e0 @msantos cleanup: move some checks to separate functions
authored
187 if (strlen(dev) >= len)
188 return -1;
189
190 for (p = dev; *p; p++) {
191 if (!isascii(*p) && !isalnum(*p) && *p != '/')
192 return -1;
193 }
194
195 return 0;
196 }
197
198
199 int
721f6a5 @msantos Support IPv6 sockets
authored
200 procket_open_socket(PROCKET_STATE *ps)
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
201 {
36d9ec6 @msantos Only look up addresses for TCP and UDP sockets
authored
202 switch (ps->protocol) {
203 case IPPROTO_TCP:
204 case IPPROTO_UDP:
205 if (procket_lookup_socket(ps) < 0)
206 return -1;
207 break;
208
209 default:
210 if (procket_create_socket(ps) < 0)
211 return -1;
212 break;
213 }
214
215 return 0;
216 }
217
218
219 int
220 procket_lookup_socket(PROCKET_STATE *ps)
221 {
721f6a5 @msantos Support IPv6 sockets
authored
222 struct addrinfo hints = {0};
223 struct addrinfo *res = NULL;
224 struct addrinfo *rp = NULL;
225 int err = 0;
226
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
227
721f6a5 @msantos Support IPv6 sockets
authored
228 hints.ai_family = ps->family;
229 hints.ai_socktype = ps->type;
230 hints.ai_protocol = ps->protocol;
4f1ae12 @msantos Avoid service lookup for port number
authored
231 hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV | AI_PASSIVE;
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
232
2b00d6f @msantos Keep port number as a char pointer
authored
233 err = getaddrinfo(ps->address, ps->port, &hints, &res);
721f6a5 @msantos Support IPv6 sockets
authored
234
994a6c7 @msantos Convert EAI_* errors to errno values
authored
235 switch (err) {
236 case 0:
237 break;
238 case EAI_SYSTEM:
239 return -1;
240
241 /* fake errno values */
242 #ifdef EAI_ADDRFAMILY
243 case EAI_ADDRFAMILY:
244 errno = EAFNOSUPPORT;
245 return -1;
246 #endif
247 case EAI_AGAIN:
248 errno = EAGAIN;
249 return -1;
250 case EAI_FAMILY:
251 errno = EPFNOSUPPORT;
252 return -1;
253 case EAI_MEMORY:
254 errno = EAI_MEMORY;
255 return -1;
256 case EAI_SERVICE:
257 case EAI_SOCKTYPE:
258 errno = ESOCKTNOSUPPORT;
259 return -1;
260 default:
261 errno = EINVAL;
262 return -1;
263 }
264
721f6a5 @msantos Support IPv6 sockets
authored
265 for (rp = res; rp != NULL; rp = rp->ai_next) {
36d9ec6 @msantos Only look up addresses for TCP and UDP sockets
authored
266 ps->family = rp->ai_family;
267 ps->type = rp->ai_socktype;
268 ps->protocol = rp->ai_protocol;
269
270 if (procket_create_socket(ps) == 0) {
271 if (bind(ps->s, rp->ai_addr, rp->ai_addrlen) < 0)
272 return -1;
721f6a5 @msantos Support IPv6 sockets
authored
273 break;
36d9ec6 @msantos Only look up addresses for TCP and UDP sockets
authored
274 }
96f8a1e @msantos Allow arbitrary socket family, type and protocol
authored
275 }
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
276
721f6a5 @msantos Support IPv6 sockets
authored
277 freeaddrinfo(res);
278
279 if (ps->s < 0)
9266617 @msantos Consistently return errors from functions
authored
280 return -1;
f9d88e0 @msantos cleanup: move some checks to separate functions
authored
281
282 return 0;
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
283 }
284
285
286 int
36d9ec6 @msantos Only look up addresses for TCP and UDP sockets
authored
287 procket_create_socket(PROCKET_STATE *ps)
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
288 {
194feb8 @msantos Add NIF versions of recvfrom/sendto
authored
289 int flags = 0;
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
290
9266617 @msantos Consistently return errors from functions
authored
291
36d9ec6 @msantos Only look up addresses for TCP and UDP sockets
authored
292 ps->s = socket(ps->family, ps->type, ps->protocol);
721f6a5 @msantos Support IPv6 sockets
authored
293
294 if (ps->s < 0)
295 return -1;
296
36d9ec6 @msantos Only look up addresses for TCP and UDP sockets
authored
297 #ifdef SO_BINDTODEVICE
298 if (ps->ifname) {
299 struct ifreq ifr;
300
301 (void)snprintf(ifr.ifr_name, IFNAMSIZ, "%s", ps->ifname);
302 if (setsockopt(ps->s, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0)
303 return -1;
304 }
305 #endif
306
721f6a5 @msantos Support IPv6 sockets
authored
307 flags = fcntl(ps->s, F_GETFL, 0);
308
309 if (flags < 0)
310 goto ERR;
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
311
721f6a5 @msantos Support IPv6 sockets
authored
312 if (fcntl(ps->s, F_SETFL, flags|O_NONBLOCK) < 0)
313 goto ERR;
314
315 return 0;
316
317 ERR:
318 if (ps->s > -1) {
5b7126e @msantos Use defined constant for sizing service buffer
authored
319 int err = errno;
721f6a5 @msantos Support IPv6 sockets
authored
320 (void)close(ps->s);
321 errno = err;
322 ps->s = -1;
323 }
324
325 return -1;
326 }
327
328
329 int
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
330 procket_pipe(PROCKET_STATE *ps)
331 {
9266617 @msantos Consistently return errors from functions
authored
332 struct sockaddr_un sa = {0};
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
333 int s = -1;
334
335
336 (void)memcpy(sa.sun_path, ps->path, sizeof(sa.sun_path)-1);
337
00214e3 @msantos Make the NIF stateless!
authored
338 sa.sun_family = PF_LOCAL;
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
339
9266617 @msantos Consistently return errors from functions
authored
340 if ( (s = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0)
341 return -1;
342
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
343 if (connect(s, (struct sockaddr *)&sa, sizeof(sa)) < 0)
9266617 @msantos Consistently return errors from functions
authored
344 return -1;
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
345
346 if (ancil_send_fd(s, ps->s) < 0)
9266617 @msantos Consistently return errors from functions
authored
347 return -1;
340157f @msantos Nit squashing.
authored
348
9266617 @msantos Consistently return errors from functions
authored
349 if (close(s) < 0)
350 return -1;
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
351
9266617 @msantos Consistently return errors from functions
authored
352 return 0;
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
353 }
354
721f6a5 @msantos Support IPv6 sockets
authored
355
bd91116 @msantos Allow setuid open of any character device
authored
356 /* character device support */
dd34004 @msantos Initial support for BPF on BSDs
authored
357 int
bd91116 @msantos Allow setuid open of any character device
authored
358 procket_open_dev(PROCKET_STATE *ps)
dd34004 @msantos Initial support for BPF on BSDs
authored
359 {
b6dadde @msantos Invalid NULL check
authored
360 char dev[MAXPATHLEN] = {0};
dd34004 @msantos Initial support for BPF on BSDs
authored
361 int i = 0;
362
bd91116 @msantos Allow setuid open of any character device
authored
363
b6dadde @msantos Invalid NULL check
authored
364 if (ps->dev == NULL) {
f9d88e0 @msantos cleanup: move some checks to separate functions
authored
365 errno = ENXIO;
366 return -1;
367 }
368
bd91116 @msantos Allow setuid open of any character device
authored
369 (void)snprintf(dev, sizeof(dev), "/dev/%s", ps->dev);
370
371 ps->s = procket_open_char_dev(dev);
372
373 if (ps->s > -1)
374 return 0;
375
376 switch (errno) {
377 case ENOENT:
378 break;
379 default:
380 return -1;
381 }
382
dd34004 @msantos Initial support for BPF on BSDs
authored
383 for (i = 0; i < 255; i++) {
bd91116 @msantos Allow setuid open of any character device
authored
384 (void)snprintf(dev, sizeof(dev), "/dev/%s%d", ps->dev, i);
dd34004 @msantos Initial support for BPF on BSDs
authored
385
bd91116 @msantos Allow setuid open of any character device
authored
386 ps->s = procket_open_char_dev(dev);
dd34004 @msantos Initial support for BPF on BSDs
authored
387
388 if (ps->s > -1)
389 return 0;
390
391 switch (errno) {
392 case EBUSY:
393 break;
394 default:
395 return -1;
396 }
397 }
398
399 return -1;
400 }
401
bd91116 @msantos Allow setuid open of any character device
authored
402 int
403 procket_open_char_dev(char *dev)
404 {
405 int fd = -1;
406 struct stat buf = {0};
407 int err = 0;
ac2d99d @msantos Mac OS X: ensure tun/tap device is non-blocking
authored
408 int flags = 0;
bd91116 @msantos Allow setuid open of any character device
authored
409
f9d88e0 @msantos cleanup: move some checks to separate functions
authored
410
ac2d99d @msantos Mac OS X: ensure tun/tap device is non-blocking
authored
411 if ( (fd = open(dev, O_RDWR)) < 0)
bd91116 @msantos Allow setuid open of any character device
authored
412 return -1;
413
ac2d99d @msantos Mac OS X: ensure tun/tap device is non-blocking
authored
414 flags = fcntl(fd, F_GETFL, 0);
415 if (flags < 0)
416 goto ERR;
417
418 if (fcntl(fd, F_SETFL, flags|O_NONBLOCK) < 0)
419 goto ERR;
420
bd91116 @msantos Allow setuid open of any character device
authored
421 /* Test the file is a character device */
ac2d99d @msantos Mac OS X: ensure tun/tap device is non-blocking
authored
422 if (fstat(fd, &buf) < 0)
bd91116 @msantos Allow setuid open of any character device
authored
423 goto ERR;
424
425 if (!S_ISCHR(buf.st_mode)) {
ac2d99d @msantos Mac OS X: ensure tun/tap device is non-blocking
authored
426 errno = ENOENT;
bd91116 @msantos Allow setuid open of any character device
authored
427 goto ERR;
428 }
429
430 return fd;
431
432 ERR:
ac2d99d @msantos Mac OS X: ensure tun/tap device is non-blocking
authored
433 if (fd > -1) {
434 err = errno;
bd91116 @msantos Allow setuid open of any character device
authored
435 (void)close(fd);
ac2d99d @msantos Mac OS X: ensure tun/tap device is non-blocking
authored
436 errno = err;
437 }
bd91116 @msantos Allow setuid open of any character device
authored
438
439 return -1;
440 }
441
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
442
443 void
d4c76dd @msantos Consistent return values from procket executable
authored
444 error_result(PROCKET_STATE *ps, int err)
445 {
446 if (ps->verbose > 0)
447 (void)fprintf(stderr, "%s", strerror(err));
448
7a64070 @msantos Return POSIX atom on error from forked setuid bin
authored
449 exit(err);
d4c76dd @msantos Consistent return values from procket executable
authored
450 }
451
452
453 void
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
454 usage(PROCKET_STATE *ps)
455 {
456 (void)fprintf(stderr, "%s, %s\n", __progname, PROCKET_VERSION);
457 (void)fprintf(stderr,
2a30b69 @msantos Figure out how to run procket setuid helper
authored
458 "usage: %s <options> <ipaddress>\n"
7bf5832 @msantos Allow setting the backlog on privileged sockets
authored
459 " -b <backlog> listen socket backlog [default:%d]\n"
721f6a5 @msantos Support IPv6 sockets
authored
460 " -u <path> path to Unix socket\n"
461 " -p <port> port\n"
462 " -F <family> family [default: PF_UNSPEC]\n"
96f8a1e @msantos Allow arbitrary socket family, type and protocol
authored
463 " -P <protocol> protocol [default: IPPROTO_TCP]\n"
464 " -T <type> type [default: SOCK_STREAM]\n"
b59dd48 @msantos Support the interface option only under Linux
authored
465 #ifdef SO_BINDTODEVICE
eba4ec3 Added option to bind a socket to a specific interface
klaar authored
466 " -I <name> interface [default: ANY]\n"
b59dd48 @msantos Support the interface option only under Linux
authored
467 #endif
bd91116 @msantos Allow setuid open of any character device
authored
468 " -d <name> open device\n"
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
469 " -v verbose mode\n",
7bf5832 @msantos Allow setting the backlog on privileged sockets
authored
470 __progname, BACKLOG
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
471 );
472
0771c28 @msantos Adjust exit values
authored
473 exit(-1);
441fde8 @msantos Interface for requesting privileged sockets in Erlang.
authored
474 }
Something went wrong with that request. Please try again.