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