ring_tx: handle EINTR from sendto
[netsniff-ng-new.git] / sock.c
blob634771bdd845d6a792bbe8c3216eda71902644b1
1 #include <sys/types.h>
2 #include <sys/socket.h>
3 #include <fcntl.h>
4 #include <arpa/inet.h>
5 #include <linux/if_ether.h>
6 #include <linux/tcp.h>
8 #include "sock.h"
9 #include "die.h"
10 #include "str.h"
11 #include "linktype.h"
12 #include "built_in.h"
13 #include "sysctl.h"
15 int af_socket(int af)
17 int sock;
19 if (unlikely(af != AF_INET && af != AF_INET6))
20 panic("Wrong AF socket type!\n");
22 sock = socket(af, SOCK_DGRAM, 0);
23 if (unlikely(sock < 0))
24 panic("Creation AF socket failed: %s\n", strerror(errno));
26 return sock;
29 int pf_socket(void)
31 int sock = socket(PF_PACKET, SOCK_RAW, 0);
32 if (unlikely(sock < 0))
33 panic("Creation of PF socket failed: %s\n", strerror(errno));
35 return sock;
38 static int pf_socket_dgram(void)
40 int sock = socket(PF_PACKET, SOCK_DGRAM, 0);
41 if (unlikely(sock < 0))
42 panic("Creation of PF dgram socket failed: %s\n",
43 strerror(errno));
45 return sock;
48 int pf_socket_type(uint32_t type)
50 switch (type) {
51 case LINKTYPE_LINUX_SLL:
52 return pf_socket_dgram();
53 default:
54 return pf_socket();
58 /* Available in kernel >= 3.14
59 * in commit d346a3fae3 (packet: introduce PACKET_QDISC_BYPASS socket option)
61 void set_sock_qdisc_bypass(int fd, bool verbose)
63 int ret, val = 1;
65 ret = setsockopt(fd, SOL_PACKET, PACKET_QDISC_BYPASS, &val, sizeof(val));
66 if (ret < 0) {
67 if (errno == ENOPROTOOPT) {
68 if (verbose)
69 printf("No kernel support for PACKET_QDISC_BYPASS"
70 " (kernel < 3.14?)\n");
71 } else
72 perror("Cannot set PACKET_QDISC_BYPASS");
73 } else
74 if (verbose) printf("Enabled kernel qdisc bypass\n");
77 void set_sock_prio(int fd, int prio)
79 int ret, val = prio;
81 ret = setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &val, sizeof(val));
82 if (unlikely(ret))
83 panic("Cannot set socket priority: %s\n", strerror(errno));
86 void set_nonblocking(int fd)
88 int ret = fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK);
89 if (unlikely(ret < 0))
90 panic("Cannot fcntl: %s\n", strerror(errno));
93 int set_nonblocking_sloppy(int fd)
95 return fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK);
98 void set_socket_keepalive(int fd)
100 int ret, one = 1;
102 ret = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one));
103 if (unlikely(ret))
104 panic("Cannot set TCP keepalive: %s\n", strerror(errno));
107 void set_tcp_nodelay(int fd)
109 int ret, one = 1;
111 ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
112 if (unlikely(ret))
113 panic("Cannot set TCP nodelay: %s\n", strerror(errno));
116 int set_ipv6_only(int fd)
118 int one = 1;
119 return setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
122 int set_reuseaddr(int fd)
124 int ret, one = 1;
126 ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
127 if (unlikely(ret < 0))
128 panic("Cannot reuse addr: %s\n", strerror(errno));
130 return 0;
133 void set_mtu_disc_dont(int fd)
135 int mtu = IP_PMTUDISC_DONT, ret;
137 ret = setsockopt(fd, SOL_IP, IP_MTU_DISCOVER, &mtu, sizeof(mtu));
138 if (unlikely(ret))
139 panic("Cannot set MTU discovery options: %s\n", strerror(errno));
142 enum {
143 sock_rmem_max = 0,
144 sock_rmem_def,
145 sock_wmem_max,
146 sock_wmem_def,
149 #define SMEM_SUG_MAX 104857600
150 #define SMEM_SUG_DEF 4194304
152 static const char *const sock_mem[] = {
153 [sock_rmem_max] = "net/core/rmem_max",
154 [sock_rmem_def] = "net/core/rmem_default",
155 [sock_wmem_max] = "net/core/wmem_max",
156 [sock_wmem_def] = "net/core/wmem_default",
159 static int get_system_socket_mem(int which)
161 int val;
163 if (sysctl_get_int(sock_mem[which], &val))
164 return -1;
166 return val;
169 static void set_system_socket_mem(int which, int val)
171 if (val > 0 && sysctl_set_int(sock_mem[which], val))
172 printf("Cannot set system socket memory in %s%s: %s\n",
173 SYSCTL_PROC_PATH, sock_mem[which], strerror(errno));
176 void set_system_socket_memory(int *vals, size_t len)
178 bug_on(len != 4);
180 if ((vals[0] = get_system_socket_mem(sock_rmem_max)) < SMEM_SUG_MAX)
181 set_system_socket_mem(sock_rmem_max, SMEM_SUG_MAX);
182 if ((vals[1] = get_system_socket_mem(sock_rmem_def)) < SMEM_SUG_DEF)
183 set_system_socket_mem(sock_rmem_def, SMEM_SUG_DEF);
184 if ((vals[2] = get_system_socket_mem(sock_wmem_max)) < SMEM_SUG_MAX)
185 set_system_socket_mem(sock_wmem_max, SMEM_SUG_MAX);
186 if ((vals[3] = get_system_socket_mem(sock_wmem_def)) < SMEM_SUG_DEF)
187 set_system_socket_mem(sock_wmem_def, SMEM_SUG_DEF);
190 void reset_system_socket_memory(int *vals, size_t len)
192 bug_on(len != 4);
194 set_system_socket_mem(sock_rmem_max, vals[0]);
195 set_system_socket_mem(sock_rmem_def, vals[1]);
196 set_system_socket_mem(sock_wmem_max, vals[2]);
197 set_system_socket_mem(sock_wmem_def, vals[3]);