1 /**
2 * @file sockopt.c Networking socket options
3 *
4 * Copyright (C) 2010 Creytiv.com
5 */
6 #ifdef HAVE_UNISTD_H
7 #include <unistd.h>
8 #endif
9 #include <fcntl.h>
10 #include <re_types.h>
11 #include <re_fmt.h>
12 #include <re_net.h>
13
14
15 #define DEBUG_MODULE "sockopt"
16 #define DEBUG_LEVEL 5
17 #include <re_dbg.h>
18
19
20 /** Platform independent buffer type cast */
21 #ifdef WIN32
22 #define BUF_CAST (char *)
23 #else
24 #define BUF_CAST
25 #endif
26
27
28 /**
29 * Set socket option blocking or non-blocking
30 *
31 * @param fd Socket file descriptor
32 * @param blocking true for blocking, false for non-blocking
33 *
34 * @return 0 if success, otherwise errorcode
35 */
net_sockopt_blocking_set(int fd,bool blocking)36 int net_sockopt_blocking_set(int fd, bool blocking)
37 {
38 #ifdef WIN32
39 unsigned long noblock = !blocking;
40 int err = 0;
41
42 if (0 != ioctlsocket(fd, FIONBIO, &noblock)) {
43 err = WSAGetLastError();
44 DEBUG_WARNING("nonblock set: fd=%d err=%d (%m)\n",
45 fd, err, err);
46 }
47 return err;
48 #else
49 int flags;
50 int err = 0;
51
52 flags = fcntl(fd, F_GETFL);
53 if (-1 == flags) {
54 err = errno;
55 DEBUG_WARNING("sockopt set: fnctl F_GETFL: (%m)\n", err);
56 goto out;
57 }
58
59 if (blocking)
60 flags &= ~O_NONBLOCK;
61 else
62 flags |= O_NONBLOCK;
63
64 if (-1 == fcntl(fd, F_SETFL, flags)) {
65 err = errno;
66 DEBUG_WARNING("sockopt set: fcntl F_SETFL non-block (%m)\n",
67 err);
68 }
69
70 out:
71 return err;
72 #endif
73 }
74
75
76 /**
77 * Set socket option to reuse address and port
78 *
79 * @param fd Socket file descriptor
80 * @param reuse true for reuse, false for no reuse
81 *
82 * @return 0 if success, otherwise errorcode
83 */
net_sockopt_reuse_set(int fd,bool reuse)84 int net_sockopt_reuse_set(int fd, bool reuse)
85 {
86 int r = reuse;
87
88 #ifdef SO_REUSEADDR
89 if (-1 == setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
90 BUF_CAST &r, sizeof(r))) {
91 DEBUG_WARNING("SO_REUSEADDR: %m\n", errno);
92 return errno;
93 }
94 #endif
95
96 #ifdef SO_REUSEPORT
97 if (-1 == setsockopt(fd, SOL_SOCKET, SO_REUSEPORT,
98 BUF_CAST &r, sizeof(r))) {
99 DEBUG_INFO("SO_REUSEPORT: %m\n", errno);
100 return errno;
101 }
102 #endif
103
104 #if !defined(SO_REUSEADDR) && !defined(SO_REUSEPORT)
105 (void)r;
106 (void)fd;
107 (void)reuse;
108 return ENOSYS;
109 #else
110 return 0;
111 #endif
112 }
113