Blame view
net/ipv4/ip_sockglue.c
40.9 KB
b24413180 License cleanup: ... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
1da177e4c Linux-2.6.12-rc2 |
2 3 4 5 6 7 |
/* * INET An implementation of the TCP/IP protocol suite for the LINUX * operating system. INET is implemented using the BSD Socket * interface as the means of communication with the user level. * * The IP to API glue. |
e905a9eda [NET] IPV4: Fix w... |
8 |
* |
1da177e4c Linux-2.6.12-rc2 |
9 10 11 12 13 |
* Authors: see ip.c * * Fixes: * Many : Split from ip.c , see ip.c for history. * Martin Mares : TOS setting fixed. |
e905a9eda [NET] IPV4: Fix w... |
14 |
* Alan Cox : Fixed a couple of oopses in Martin's |
1da177e4c Linux-2.6.12-rc2 |
15 16 17 |
* TOS tweaks. * Mike McLagan : Routing by source */ |
1da177e4c Linux-2.6.12-rc2 |
18 19 20 |
#include <linux/module.h> #include <linux/types.h> #include <linux/mm.h> |
1da177e4c Linux-2.6.12-rc2 |
21 22 23 |
#include <linux/skbuff.h> #include <linux/ip.h> #include <linux/icmp.h> |
14c850212 [INET_SOCK]: Move... |
24 |
#include <linux/inetdevice.h> |
1da177e4c Linux-2.6.12-rc2 |
25 |
#include <linux/netdevice.h> |
5a0e3ad6a include cleanup: ... |
26 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
27 28 29 |
#include <net/sock.h> #include <net/ip.h> #include <net/icmp.h> |
d83d8461f [IP_SOCKGLUE]: Re... |
30 |
#include <net/tcp_states.h> |
1da177e4c Linux-2.6.12-rc2 |
31 32 33 34 35 |
#include <linux/udp.h> #include <linux/igmp.h> #include <linux/netfilter.h> #include <linux/route.h> #include <linux/mroute.h> |
2c67e9acb net: use INET_ECN... |
36 |
#include <net/inet_ecn.h> |
1da177e4c Linux-2.6.12-rc2 |
37 38 |
#include <net/route.h> #include <net/xfrm.h> |
dae502954 ipv4/ipv6 compat:... |
39 |
#include <net/compat.h> |
ad6f939ab ip: Add offset pa... |
40 |
#include <net/checksum.h> |
dfd56b8b3 net: use IS_ENABL... |
41 |
#if IS_ENABLED(CONFIG_IPV6) |
1da177e4c Linux-2.6.12-rc2 |
42 43 |
#include <net/transp_v6.h> #endif |
35ebf65e8 ipv4: Create and ... |
44 |
#include <net/ip_fib.h> |
1da177e4c Linux-2.6.12-rc2 |
45 46 |
#include <linux/errqueue.h> |
7c0f6ba68 Replace <asm/uacc... |
47 |
#include <linux/uaccess.h> |
1da177e4c Linux-2.6.12-rc2 |
48 |
|
d2ba09c17 net: add skeleton... |
49 |
#include <linux/bpfilter.h> |
1da177e4c Linux-2.6.12-rc2 |
50 51 52 53 54 55 |
/* * SOL_IP control messages. */ static void ip_cmsg_recv_pktinfo(struct msghdr *msg, struct sk_buff *skb) { |
d826eb14e ipv4: PKTINFO doe... |
56 |
struct in_pktinfo info = *PKTINFO_SKB_CB(skb); |
1da177e4c Linux-2.6.12-rc2 |
57 |
|
eddc9ec53 [SK_BUFF]: Introd... |
58 |
info.ipi_addr.s_addr = ip_hdr(skb)->daddr; |
1da177e4c Linux-2.6.12-rc2 |
59 60 61 62 63 64 |
put_cmsg(msg, SOL_IP, IP_PKTINFO, sizeof(info), &info); } static void ip_cmsg_recv_ttl(struct msghdr *msg, struct sk_buff *skb) { |
eddc9ec53 [SK_BUFF]: Introd... |
65 |
int ttl = ip_hdr(skb)->ttl; |
1da177e4c Linux-2.6.12-rc2 |
66 67 68 69 70 |
put_cmsg(msg, SOL_IP, IP_TTL, sizeof(int), &ttl); } static void ip_cmsg_recv_tos(struct msghdr *msg, struct sk_buff *skb) { |
eddc9ec53 [SK_BUFF]: Introd... |
71 |
put_cmsg(msg, SOL_IP, IP_TOS, 1, &ip_hdr(skb)->tos); |
1da177e4c Linux-2.6.12-rc2 |
72 73 74 75 76 77 |
} static void ip_cmsg_recv_opts(struct msghdr *msg, struct sk_buff *skb) { if (IPCB(skb)->opt.optlen == 0) return; |
eddc9ec53 [SK_BUFF]: Introd... |
78 79 |
put_cmsg(msg, SOL_IP, IP_RECVOPTS, IPCB(skb)->opt.optlen, ip_hdr(skb) + 1); |
1da177e4c Linux-2.6.12-rc2 |
80 |
} |
91ed1e666 ip/options: expli... |
81 82 |
static void ip_cmsg_recv_retopts(struct net *net, struct msghdr *msg, struct sk_buff *skb) |
1da177e4c Linux-2.6.12-rc2 |
83 84 |
{ unsigned char optbuf[sizeof(struct ip_options) + 40]; |
5e73ea1a3 ipv4: fix checkpa... |
85 |
struct ip_options *opt = (struct ip_options *)optbuf; |
1da177e4c Linux-2.6.12-rc2 |
86 87 88 |
if (IPCB(skb)->opt.optlen == 0) return; |
91ed1e666 ip/options: expli... |
89 |
if (ip_options_echo(net, opt, skb)) { |
1da177e4c Linux-2.6.12-rc2 |
90 91 92 93 94 95 96 |
msg->msg_flags |= MSG_CTRUNC; return; } ip_options_undo(opt); put_cmsg(msg, SOL_IP, IP_RETOPTS, opt->optlen, opt->__data); } |
70ecc2484 ipv4: add IP_RECV... |
97 98 99 100 101 102 103 104 105 106 |
static void ip_cmsg_recv_fragsize(struct msghdr *msg, struct sk_buff *skb) { int val; if (IPCB(skb)->frag_max_size == 0) return; val = IPCB(skb)->frag_max_size; put_cmsg(msg, SOL_IP, IP_RECVFRAGSIZE, sizeof(val), &val); } |
ad6f939ab ip: Add offset pa... |
107 |
static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb, |
10df8e615 udp: fix IP_CHECK... |
108 |
int tlen, int offset) |
ad6f939ab ip: Add offset pa... |
109 110 111 112 113 |
{ __wsum csum = skb->csum; if (skb->ip_summed != CHECKSUM_COMPLETE) return; |
ca4ef4574 ip: fix IP_CHECKS... |
114 115 116 117 |
if (offset != 0) { int tend_off = skb_transport_offset(skb) + tlen; csum = csum_sub(csum, skb_checksum(skb, tend_off, offset, 0)); } |
ad6f939ab ip: Add offset pa... |
118 119 120 |
put_cmsg(msg, SOL_IP, IP_CHECKSUM, sizeof(__wsum), &csum); } |
2c7946a7b [SECURITY]: TCP/U... |
121 122 123 |
static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb) { char *secdata; |
dc49c1f94 [AF_UNIX]: Kernel... |
124 |
u32 seclen, secid; |
2c7946a7b [SECURITY]: TCP/U... |
125 |
int err; |
dc49c1f94 [AF_UNIX]: Kernel... |
126 127 128 129 130 |
err = security_socket_getpeersec_dgram(NULL, skb, &secid); if (err) return; err = security_secid_to_secctx(secid, &secdata, &seclen); |
2c7946a7b [SECURITY]: TCP/U... |
131 132 133 134 |
if (err) return; put_cmsg(msg, SOL_IP, SCM_SECURITY, seclen, secdata); |
dc49c1f94 [AF_UNIX]: Kernel... |
135 |
security_release_secctx(secdata, seclen); |
2c7946a7b [SECURITY]: TCP/U... |
136 |
} |
21d1a161f net: ip_sockglue.... |
137 |
static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb) |
e8b2dfe9b TPROXY: implement... |
138 |
{ |
4a06fa67c ip: on queued skb... |
139 |
__be16 _ports[2], *ports; |
e8b2dfe9b TPROXY: implement... |
140 |
struct sockaddr_in sin; |
e8b2dfe9b TPROXY: implement... |
141 142 143 144 145 |
/* All current transport protocols have the port numbers in the * first four bytes of the transport header and this function is * written with this assumption in mind. */ |
4a06fa67c ip: on queued skb... |
146 147 148 149 |
ports = skb_header_pointer(skb, skb_transport_offset(skb), sizeof(_ports), &_ports); if (!ports) return; |
e8b2dfe9b TPROXY: implement... |
150 151 |
sin.sin_family = AF_INET; |
64199fc0a ipv4: fix use-aft... |
152 |
sin.sin_addr.s_addr = ip_hdr(skb)->daddr; |
e8b2dfe9b TPROXY: implement... |
153 154 155 156 157 |
sin.sin_port = ports[1]; memset(sin.sin_zero, 0, sizeof(sin.sin_zero)); put_cmsg(msg, SOL_IP, IP_ORIGDSTADDR, sizeof(sin), &sin); } |
1da177e4c Linux-2.6.12-rc2 |
158 |
|
ad959036a net/sock: add an ... |
159 160 |
void ip_cmsg_recv_offset(struct msghdr *msg, struct sock *sk, struct sk_buff *skb, int tlen, int offset) |
1da177e4c Linux-2.6.12-rc2 |
161 |
{ |
ad959036a net/sock: add an ... |
162 |
struct inet_sock *inet = inet_sk(sk); |
95c961747 net: cleanup unsi... |
163 |
unsigned int flags = inet->cmsg_flags; |
1da177e4c Linux-2.6.12-rc2 |
164 165 |
/* Ordered by supposed usage frequency */ |
c44d13d6f ip: IP cmsg cleanup |
166 |
if (flags & IP_CMSG_PKTINFO) { |
1da177e4c Linux-2.6.12-rc2 |
167 |
ip_cmsg_recv_pktinfo(msg, skb); |
1da177e4c Linux-2.6.12-rc2 |
168 |
|
c44d13d6f ip: IP cmsg cleanup |
169 170 171 172 173 174 |
flags &= ~IP_CMSG_PKTINFO; if (!flags) return; } if (flags & IP_CMSG_TTL) { |
1da177e4c Linux-2.6.12-rc2 |
175 |
ip_cmsg_recv_ttl(msg, skb); |
1da177e4c Linux-2.6.12-rc2 |
176 |
|
c44d13d6f ip: IP cmsg cleanup |
177 178 179 180 181 182 |
flags &= ~IP_CMSG_TTL; if (!flags) return; } if (flags & IP_CMSG_TOS) { |
1da177e4c Linux-2.6.12-rc2 |
183 |
ip_cmsg_recv_tos(msg, skb); |
1da177e4c Linux-2.6.12-rc2 |
184 |
|
c44d13d6f ip: IP cmsg cleanup |
185 186 187 188 189 190 |
flags &= ~IP_CMSG_TOS; if (!flags) return; } if (flags & IP_CMSG_RECVOPTS) { |
1da177e4c Linux-2.6.12-rc2 |
191 |
ip_cmsg_recv_opts(msg, skb); |
1da177e4c Linux-2.6.12-rc2 |
192 |
|
c44d13d6f ip: IP cmsg cleanup |
193 194 195 196 197 198 |
flags &= ~IP_CMSG_RECVOPTS; if (!flags) return; } if (flags & IP_CMSG_RETOPTS) { |
91ed1e666 ip/options: expli... |
199 |
ip_cmsg_recv_retopts(sock_net(sk), msg, skb); |
2c7946a7b [SECURITY]: TCP/U... |
200 |
|
c44d13d6f ip: IP cmsg cleanup |
201 202 203 204 205 206 |
flags &= ~IP_CMSG_RETOPTS; if (!flags) return; } if (flags & IP_CMSG_PASSSEC) { |
2c7946a7b [SECURITY]: TCP/U... |
207 |
ip_cmsg_recv_security(msg, skb); |
e8b2dfe9b TPROXY: implement... |
208 |
|
c44d13d6f ip: IP cmsg cleanup |
209 210 211 212 |
flags &= ~IP_CMSG_PASSSEC; if (!flags) return; } |
ad6f939ab ip: Add offset pa... |
213 |
if (flags & IP_CMSG_ORIGDSTADDR) { |
e8b2dfe9b TPROXY: implement... |
214 |
ip_cmsg_recv_dstaddr(msg, skb); |
ad6f939ab ip: Add offset pa... |
215 216 217 218 219 220 |
flags &= ~IP_CMSG_ORIGDSTADDR; if (!flags) return; } if (flags & IP_CMSG_CHECKSUM) |
10df8e615 udp: fix IP_CHECK... |
221 |
ip_cmsg_recv_checksum(msg, skb, tlen, offset); |
70ecc2484 ipv4: add IP_RECV... |
222 223 224 |
if (flags & IP_CMSG_RECVFRAGSIZE) ip_cmsg_recv_fragsize(msg, skb); |
1da177e4c Linux-2.6.12-rc2 |
225 |
} |
5961de9f1 ip: Add offset pa... |
226 |
EXPORT_SYMBOL(ip_cmsg_recv_offset); |
1da177e4c Linux-2.6.12-rc2 |
227 |
|
24025c465 ipv4: process soc... |
228 |
int ip_cmsg_send(struct sock *sk, struct msghdr *msg, struct ipcm_cookie *ipc, |
c8e6ad082 ipv6: honor IPV6_... |
229 |
bool allow_ipv6) |
1da177e4c Linux-2.6.12-rc2 |
230 |
{ |
f02db315b ipv4: IP_TOS and ... |
231 |
int err, val; |
1da177e4c Linux-2.6.12-rc2 |
232 |
struct cmsghdr *cmsg; |
24025c465 ipv4: process soc... |
233 |
struct net *net = sock_net(sk); |
1da177e4c Linux-2.6.12-rc2 |
234 |
|
f95b414ed net: introduce he... |
235 |
for_each_cmsghdr(cmsg, msg) { |
1da177e4c Linux-2.6.12-rc2 |
236 237 |
if (!CMSG_OK(msg, cmsg)) return -EINVAL; |
5337b5b75 ipv6: fix IPV6_PK... |
238 |
#if IS_ENABLED(CONFIG_IPV6) |
c8e6ad082 ipv6: honor IPV6_... |
239 240 241 242 243 244 245 246 247 248 |
if (allow_ipv6 && cmsg->cmsg_level == SOL_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) { struct in6_pktinfo *src_info; if (cmsg->cmsg_len < CMSG_LEN(sizeof(*src_info))) return -EINVAL; src_info = (struct in6_pktinfo *)CMSG_DATA(cmsg); if (!ipv6_addr_v4mapped(&src_info->ipi6_addr)) return -EINVAL; |
1cbec0764 net: Only honor i... |
249 250 |
if (src_info->ipi6_ifindex) ipc->oif = src_info->ipi6_ifindex; |
c8e6ad082 ipv6: honor IPV6_... |
251 252 253 254 |
ipc->addr = src_info->ipi6_addr.s6_addr32[3]; continue; } #endif |
24025c465 ipv4: process soc... |
255 |
if (cmsg->cmsg_level == SOL_SOCKET) { |
2632616bc sock: propagate _... |
256 257 258 |
err = __sock_cmsg_send(sk, msg, cmsg, &ipc->sockc); if (err) return err; |
24025c465 ipv4: process soc... |
259 260 |
continue; } |
1da177e4c Linux-2.6.12-rc2 |
261 262 263 264 |
if (cmsg->cmsg_level != SOL_IP) continue; switch (cmsg->cmsg_type) { case IP_RETOPTS: |
1ff8cebf4 scm: remove use C... |
265 |
err = cmsg->cmsg_len - sizeof(struct cmsghdr); |
919483096 ipv4: fix memory ... |
266 267 |
/* Our caller is responsible for freeing ipc->opt */ |
de40a3e88 net/ipv4: merge i... |
268 269 |
err = ip_options_get(net, &ipc->opt, KERNEL_SOCKPTR(CMSG_DATA(cmsg)), |
4d52cfbef net: ipv4/ip_sock... |
270 |
err < 40 ? err : 40); |
1da177e4c Linux-2.6.12-rc2 |
271 272 273 274 275 276 277 278 279 |
if (err) return err; break; case IP_PKTINFO: { struct in_pktinfo *info; if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct in_pktinfo))) return -EINVAL; info = (struct in_pktinfo *)CMSG_DATA(cmsg); |
1cbec0764 net: Only honor i... |
280 281 |
if (info->ipi_ifindex) ipc->oif = info->ipi_ifindex; |
1da177e4c Linux-2.6.12-rc2 |
282 283 284 |
ipc->addr = info->ipi_spec_dst.s_addr; break; } |
f02db315b ipv4: IP_TOS and ... |
285 286 287 288 289 290 291 292 293 |
case IP_TTL: if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) return -EINVAL; val = *(int *)CMSG_DATA(cmsg); if (val < 1 || val > 255) return -EINVAL; ipc->ttl = val; break; case IP_TOS: |
e895cdce6 ipv4: accept u8 i... |
294 295 296 297 298 |
if (cmsg->cmsg_len == CMSG_LEN(sizeof(int))) val = *(int *)CMSG_DATA(cmsg); else if (cmsg->cmsg_len == CMSG_LEN(sizeof(u8))) val = *(u8 *)CMSG_DATA(cmsg); else |
f02db315b ipv4: IP_TOS and ... |
299 |
return -EINVAL; |
f02db315b ipv4: IP_TOS and ... |
300 301 302 303 304 |
if (val < 0 || val > 255) return -EINVAL; ipc->tos = val; ipc->priority = rt_tos2priority(ipc->tos); break; |
1da177e4c Linux-2.6.12-rc2 |
305 306 307 308 309 310 |
default: return -EINVAL; } } return 0; } |
592fcb9df ip: ip_ra_control... |
311 |
static void ip_ra_destroy_rcu(struct rcu_head *head) |
66018506e ip: Router Alert ... |
312 |
{ |
592fcb9df ip: ip_ra_control... |
313 314 315 316 |
struct ip_ra_chain *ra = container_of(head, struct ip_ra_chain, rcu); sock_put(ra->saved_sk); kfree(ra); |
66018506e ip: Router Alert ... |
317 |
} |
1da177e4c Linux-2.6.12-rc2 |
318 |
|
4d52cfbef net: ipv4/ip_sock... |
319 320 |
int ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct sock *)) |
1da177e4c Linux-2.6.12-rc2 |
321 |
{ |
43a951e99 ipv4: add __rcu a... |
322 323 |
struct ip_ra_chain *ra, *new_ra; struct ip_ra_chain __rcu **rap; |
5796ef75e net: Make ip_ra_c... |
324 |
struct net *net = sock_net(sk); |
1da177e4c Linux-2.6.12-rc2 |
325 |
|
c720c7e83 inet: rename some... |
326 |
if (sk->sk_type != SOCK_RAW || inet_sk(sk)->inet_num == IPPROTO_RAW) |
1da177e4c Linux-2.6.12-rc2 |
327 328 329 |
return -EINVAL; new_ra = on ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL; |
425aa0e1d ip_sockglue: Fix ... |
330 331 |
if (on && !new_ra) return -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
332 |
|
d9ff30497 net: Replace ip_r... |
333 |
mutex_lock(&net->ipv4.ra_mutex); |
5796ef75e net: Make ip_ra_c... |
334 |
for (rap = &net->ipv4.ra_chain; |
76d3e153d net: Revert "ipv4... |
335 |
(ra = rcu_dereference_protected(*rap, |
d9ff30497 net: Replace ip_r... |
336 |
lockdep_is_held(&net->ipv4.ra_mutex))) != NULL; |
43a951e99 ipv4: add __rcu a... |
337 |
rap = &ra->next) { |
1da177e4c Linux-2.6.12-rc2 |
338 339 |
if (ra->sk == sk) { if (on) { |
d9ff30497 net: Replace ip_r... |
340 |
mutex_unlock(&net->ipv4.ra_mutex); |
a51482bde [NET]: kfree cleanup |
341 |
kfree(new_ra); |
1da177e4c Linux-2.6.12-rc2 |
342 343 |
return -EADDRINUSE; } |
592fcb9df ip: ip_ra_control... |
344 345 |
/* dont let ip_call_ra_chain() use sk again */ ra->sk = NULL; |
8e380f004 ipv4: rcu cleanup... |
346 |
RCU_INIT_POINTER(*rap, ra->next); |
d9ff30497 net: Replace ip_r... |
347 |
mutex_unlock(&net->ipv4.ra_mutex); |
1da177e4c Linux-2.6.12-rc2 |
348 349 350 |
if (ra->destructor) ra->destructor(sk); |
592fcb9df ip: ip_ra_control... |
351 352 353 354 355 356 357 |
/* * Delay sock_put(sk) and kfree(ra) after one rcu grace * period. This guarantee ip_call_ra_chain() dont need * to mess with socket refcounts. */ ra->saved_sk = sk; call_rcu(&ra->rcu, ip_ra_destroy_rcu); |
1da177e4c Linux-2.6.12-rc2 |
358 359 360 |
return 0; } } |
76d3e153d net: Revert "ipv4... |
361 |
if (!new_ra) { |
d9ff30497 net: Replace ip_r... |
362 |
mutex_unlock(&net->ipv4.ra_mutex); |
1da177e4c Linux-2.6.12-rc2 |
363 |
return -ENOBUFS; |
76d3e153d net: Revert "ipv4... |
364 |
} |
1da177e4c Linux-2.6.12-rc2 |
365 366 |
new_ra->sk = sk; new_ra->destructor = destructor; |
8e380f004 ipv4: rcu cleanup... |
367 |
RCU_INIT_POINTER(new_ra->next, ra); |
66018506e ip: Router Alert ... |
368 |
rcu_assign_pointer(*rap, new_ra); |
1da177e4c Linux-2.6.12-rc2 |
369 |
sock_hold(sk); |
d9ff30497 net: Replace ip_r... |
370 |
mutex_unlock(&net->ipv4.ra_mutex); |
1da177e4c Linux-2.6.12-rc2 |
371 372 373 |
return 0; } |
178c49d9f icmp: prepare rfc... |
374 375 376 377 378 379 380 381 382 383 384 |
static void ipv4_icmp_error_rfc4884(const struct sk_buff *skb, struct sock_ee_data_rfc4884 *out) { switch (icmp_hdr(skb)->type) { case ICMP_DEST_UNREACH: case ICMP_TIME_EXCEEDED: case ICMP_PARAMETERPROB: ip_icmp_error_rfc4884(skb, out, sizeof(struct icmphdr), icmp_hdr(skb)->un.reserved[1] * 4); } } |
e905a9eda [NET] IPV4: Fix w... |
385 |
void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, |
35986b329 [IPV4]: ip_icmp_e... |
386 |
__be16 port, u32 info, u8 *payload) |
1da177e4c Linux-2.6.12-rc2 |
387 |
{ |
1da177e4c Linux-2.6.12-rc2 |
388 |
struct sock_exterr_skb *serr; |
1da177e4c Linux-2.6.12-rc2 |
389 390 391 |
skb = skb_clone(skb, GFP_ATOMIC); if (!skb) return; |
e905a9eda [NET] IPV4: Fix w... |
392 |
serr = SKB_EXT_ERR(skb); |
1da177e4c Linux-2.6.12-rc2 |
393 394 |
serr->ee.ee_errno = err; serr->ee.ee_origin = SO_EE_ORIGIN_ICMP; |
88c7664f1 [SK_BUFF]: Introd... |
395 396 |
serr->ee.ee_type = icmp_hdr(skb)->type; serr->ee.ee_code = icmp_hdr(skb)->code; |
1da177e4c Linux-2.6.12-rc2 |
397 398 399 |
serr->ee.ee_pad = 0; serr->ee.ee_info = info; serr->ee.ee_data = 0; |
88c7664f1 [SK_BUFF]: Introd... |
400 |
serr->addr_offset = (u8 *)&(((struct iphdr *)(icmp_hdr(skb) + 1))->daddr) - |
d56f90a7c [SK_BUFF]: Introd... |
401 |
skb_network_header(skb); |
1da177e4c Linux-2.6.12-rc2 |
402 |
serr->port = port; |
00db41243 ipv4: coding styl... |
403 |
if (skb_pull(skb, payload - skb->data)) { |
eba75c587 icmp: support rfc... |
404 |
if (inet_sk(sk)->recverr_rfc4884) |
178c49d9f icmp: prepare rfc... |
405 |
ipv4_icmp_error_rfc4884(skb, &serr->ee.ee_rfc4884); |
eba75c587 icmp: support rfc... |
406 |
|
bd82393ca [SK_BUFF]: More s... |
407 408 409 410 411 |
skb_reset_transport_header(skb); if (sock_queue_err_skb(sk, skb) == 0) return; } kfree_skb(skb); |
1da177e4c Linux-2.6.12-rc2 |
412 |
} |
0579016ec [IPV4]: ip_local_... |
413 |
void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 port, u32 info) |
1da177e4c Linux-2.6.12-rc2 |
414 415 416 417 418 419 420 421 422 423 424 425 |
{ struct inet_sock *inet = inet_sk(sk); struct sock_exterr_skb *serr; struct iphdr *iph; struct sk_buff *skb; if (!inet->recverr) return; skb = alloc_skb(sizeof(struct iphdr), GFP_ATOMIC); if (!skb) return; |
2ca9e6f2c [SK_BUFF]: Some m... |
426 427 |
skb_put(skb, sizeof(struct iphdr)); skb_reset_network_header(skb); |
eddc9ec53 [SK_BUFF]: Introd... |
428 |
iph = ip_hdr(skb); |
1da177e4c Linux-2.6.12-rc2 |
429 |
iph->daddr = daddr; |
e905a9eda [NET] IPV4: Fix w... |
430 |
serr = SKB_EXT_ERR(skb); |
1da177e4c Linux-2.6.12-rc2 |
431 432 |
serr->ee.ee_errno = err; serr->ee.ee_origin = SO_EE_ORIGIN_LOCAL; |
e905a9eda [NET] IPV4: Fix w... |
433 |
serr->ee.ee_type = 0; |
1da177e4c Linux-2.6.12-rc2 |
434 435 436 437 |
serr->ee.ee_code = 0; serr->ee.ee_pad = 0; serr->ee.ee_info = info; serr->ee.ee_data = 0; |
d56f90a7c [SK_BUFF]: Introd... |
438 |
serr->addr_offset = (u8 *)&iph->daddr - skb_network_header(skb); |
1da177e4c Linux-2.6.12-rc2 |
439 |
serr->port = port; |
27a884dc3 [SK_BUFF]: Conver... |
440 |
__skb_pull(skb, skb_tail_pointer(skb) - skb->data); |
bd82393ca [SK_BUFF]: More s... |
441 |
skb_reset_transport_header(skb); |
1da177e4c Linux-2.6.12-rc2 |
442 443 444 445 |
if (sock_queue_err_skb(sk, skb)) kfree_skb(skb); } |
34b99df4e ip: report the or... |
446 447 448 449 450 451 452 453 |
/* For some errors we have valid addr_offset even with zero payload and * zero port. Also, addr_offset should be supported if port is set. */ static inline bool ipv4_datagram_support_addr(struct sock_exterr_skb *serr) { return serr->ee.ee_origin == SO_EE_ORIGIN_ICMP || serr->ee.ee_origin == SO_EE_ORIGIN_LOCAL || serr->port; } |
c247f0534 ip: fix error que... |
454 455 456 457 458 459 460 461 |
/* IPv4 supports cmsg on all imcp errors and some timestamps * * Timestamp code paths do not initialize the fields expected by cmsg: * the PKTINFO fields in skb->cb[]. Fill those in here. */ static bool ipv4_datagram_support_cmsg(const struct sock *sk, struct sk_buff *skb, int ee_origin) |
829ae9d61 net-timestamp: al... |
462 |
{ |
c247f0534 ip: fix error que... |
463 464 465 466 |
struct in_pktinfo *info; if (ee_origin == SO_EE_ORIGIN_ICMP) return true; |
829ae9d61 net-timestamp: al... |
467 |
|
c247f0534 ip: fix error que... |
468 469 470 471 |
if (ee_origin == SO_EE_ORIGIN_LOCAL) return false; /* Support IP_PKTINFO on tstamp packets if requested, to correlate |
1862d6208 net-timestamp: av... |
472 |
* timestamp with egress dev. Not possible for packets without iif |
c247f0534 ip: fix error que... |
473 474 |
* or without payload (SOF_TIMESTAMPING_OPT_TSONLY). */ |
1862d6208 net-timestamp: av... |
475 476 477 |
info = PKTINFO_SKB_CB(skb); if (!(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_CMSG) || !info->ipi_ifindex) |
829ae9d61 net-timestamp: al... |
478 479 480 |
return false; info->ipi_spec_dst.s_addr = ip_hdr(skb)->saddr; |
829ae9d61 net-timestamp: al... |
481 482 |
return true; } |
e905a9eda [NET] IPV4: Fix w... |
483 |
/* |
1da177e4c Linux-2.6.12-rc2 |
484 485 |
* Handle MSG_ERRQUEUE */ |
85fbaa750 inet: fix addr_le... |
486 |
int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) |
1da177e4c Linux-2.6.12-rc2 |
487 488 |
{ struct sock_exterr_skb *serr; |
364a9e932 sock: deduplicate... |
489 |
struct sk_buff *skb; |
342dfc306 net: add build-ti... |
490 |
DECLARE_SOCKADDR(struct sockaddr_in *, sin, msg->msg_name); |
1da177e4c Linux-2.6.12-rc2 |
491 492 493 494 495 496 497 498 |
struct { struct sock_extended_err ee; struct sockaddr_in offender; } errhdr; int err; int copied; err = -EAGAIN; |
364a9e932 sock: deduplicate... |
499 |
skb = sock_dequeue_err_skb(sk); |
51456b291 ipv4: coding styl... |
500 |
if (!skb) |
1da177e4c Linux-2.6.12-rc2 |
501 502 503 504 505 506 507 |
goto out; copied = skb->len; if (copied > len) { msg->msg_flags |= MSG_TRUNC; copied = len; } |
51f3d02b9 net: Add and use ... |
508 |
err = skb_copy_datagram_msg(skb, 0, msg, copied); |
960a26282 net: better drop ... |
509 510 511 512 |
if (unlikely(err)) { kfree_skb(skb); return err; } |
1da177e4c Linux-2.6.12-rc2 |
513 514 515 |
sock_recv_timestamp(msg, sk, skb); serr = SKB_EXT_ERR(skb); |
34b99df4e ip: report the or... |
516 |
if (sin && ipv4_datagram_support_addr(serr)) { |
1da177e4c Linux-2.6.12-rc2 |
517 |
sin->sin_family = AF_INET; |
d56f90a7c [SK_BUFF]: Introd... |
518 519 |
sin->sin_addr.s_addr = *(__be32 *)(skb_network_header(skb) + serr->addr_offset); |
1da177e4c Linux-2.6.12-rc2 |
520 521 |
sin->sin_port = serr->port; memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); |
85fbaa750 inet: fix addr_le... |
522 |
*addr_len = sizeof(*sin); |
1da177e4c Linux-2.6.12-rc2 |
523 524 525 526 |
} memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); sin = &errhdr.offender; |
f812116b1 ip: zero sockaddr... |
527 |
memset(sin, 0, sizeof(*sin)); |
829ae9d61 net-timestamp: al... |
528 |
|
c247f0534 ip: fix error que... |
529 |
if (ipv4_datagram_support_cmsg(sk, skb, serr->ee.ee_origin)) { |
1da177e4c Linux-2.6.12-rc2 |
530 |
sin->sin_family = AF_INET; |
eddc9ec53 [SK_BUFF]: Introd... |
531 |
sin->sin_addr.s_addr = ip_hdr(skb)->saddr; |
f812116b1 ip: zero sockaddr... |
532 |
if (inet_sk(sk)->cmsg_flags) |
1da177e4c Linux-2.6.12-rc2 |
533 534 535 536 537 538 539 540 541 |
ip_cmsg_recv(msg, skb); } put_cmsg(msg, SOL_IP, IP_RECVERR, sizeof(errhdr), &errhdr); /* Now we could try to dump offended packet options */ msg->msg_flags |= MSG_ERRQUEUE; err = copied; |
960a26282 net: better drop ... |
542 |
consume_skb(skb); |
1da177e4c Linux-2.6.12-rc2 |
543 544 545 |
out: return err; } |
6ebf71bab ipv4: add ip_sock... |
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 |
static void __ip_sock_set_tos(struct sock *sk, int val) { if (sk->sk_type == SOCK_STREAM) { val &= ~INET_ECN_MASK; val |= inet_sk(sk)->tos & INET_ECN_MASK; } if (inet_sk(sk)->tos != val) { inet_sk(sk)->tos = val; sk->sk_priority = rt_tos2priority(val); sk_dst_reset(sk); } } void ip_sock_set_tos(struct sock *sk, int val) { lock_sock(sk); __ip_sock_set_tos(sk, val); release_sock(sk); } EXPORT_SYMBOL(ip_sock_set_tos); |
1da177e4c Linux-2.6.12-rc2 |
566 |
|
c4e446bf5 ipv4: add ip_sock... |
567 568 569 570 571 572 573 |
void ip_sock_set_freebind(struct sock *sk) { lock_sock(sk); inet_sk(sk)->freebind = true; release_sock(sk); } EXPORT_SYMBOL(ip_sock_set_freebind); |
db45c0ef2 ipv4: add ip_sock... |
574 575 576 577 578 579 580 |
void ip_sock_set_recverr(struct sock *sk) { lock_sock(sk); inet_sk(sk)->recverr = true; release_sock(sk); } EXPORT_SYMBOL(ip_sock_set_recverr); |
2de569bda ipv4: add ip_sock... |
581 582 583 584 585 586 587 588 589 590 |
int ip_sock_set_mtu_discover(struct sock *sk, int val) { if (val < IP_PMTUDISC_DONT || val > IP_PMTUDISC_OMIT) return -EINVAL; lock_sock(sk); inet_sk(sk)->pmtudisc = val; release_sock(sk); return 0; } EXPORT_SYMBOL(ip_sock_set_mtu_discover); |
c1f9ec577 ipv4: add ip_sock... |
591 592 593 594 595 596 597 |
void ip_sock_set_pktinfo(struct sock *sk) { lock_sock(sk); inet_sk(sk)->cmsg_flags |= IP_CMSG_PKTINFO; release_sock(sk); } EXPORT_SYMBOL(ip_sock_set_pktinfo); |
1da177e4c Linux-2.6.12-rc2 |
598 |
/* |
4d52cfbef net: ipv4/ip_sock... |
599 600 |
* Socket option code for IP. This is the end of the line after any * TCP,UDP etc options on an IP socket. |
1da177e4c Linux-2.6.12-rc2 |
601 |
*/ |
baf606d9c ipv4,ipv6: grab r... |
602 603 604 605 606 |
static bool setsockopt_needs_rtnl(int optname) { switch (optname) { case IP_ADD_MEMBERSHIP: case IP_ADD_SOURCE_MEMBERSHIP: |
54ff9ef36 ipv4, ipv6: kill ... |
607 |
case IP_BLOCK_SOURCE: |
baf606d9c ipv4,ipv6: grab r... |
608 |
case IP_DROP_MEMBERSHIP: |
54ff9ef36 ipv4, ipv6: kill ... |
609 610 611 612 613 |
case IP_DROP_SOURCE_MEMBERSHIP: case IP_MSFILTER: case IP_UNBLOCK_SOURCE: case MCAST_BLOCK_SOURCE: case MCAST_MSFILTER: |
baf606d9c ipv4,ipv6: grab r... |
614 |
case MCAST_JOIN_GROUP: |
54ff9ef36 ipv4, ipv6: kill ... |
615 |
case MCAST_JOIN_SOURCE_GROUP: |
baf606d9c ipv4,ipv6: grab r... |
616 |
case MCAST_LEAVE_GROUP: |
54ff9ef36 ipv4, ipv6: kill ... |
617 618 |
case MCAST_LEAVE_SOURCE_GROUP: case MCAST_UNBLOCK_SOURCE: |
baf606d9c ipv4,ipv6: grab r... |
619 620 621 622 |
return true; } return false; } |
1da177e4c Linux-2.6.12-rc2 |
623 |
|
e986d4dab set_mcast_msfilte... |
624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 |
static int set_mcast_msfilter(struct sock *sk, int ifindex, int numsrc, int fmode, struct sockaddr_storage *group, struct sockaddr_storage *list) { int msize = IP_MSFILTER_SIZE(numsrc); struct ip_msfilter *msf; struct sockaddr_in *psin; int err, i; msf = kmalloc(msize, GFP_KERNEL); if (!msf) return -ENOBUFS; psin = (struct sockaddr_in *)group; if (psin->sin_family != AF_INET) goto Eaddrnotavail; msf->imsf_multiaddr = psin->sin_addr.s_addr; msf->imsf_interface = 0; msf->imsf_fmode = fmode; msf->imsf_numsrc = numsrc; for (i = 0; i < numsrc; ++i) { psin = (struct sockaddr_in *)&list[i]; if (psin->sin_family != AF_INET) goto Eaddrnotavail; msf->imsf_slist[i] = psin->sin_addr.s_addr; } err = ip_mc_msfilter(sk, msf, ifindex); kfree(msf); return err; Eaddrnotavail: kfree(msf); return -EADDRNOTAVAIL; } |
89654c5fc net/ipv4: switch ... |
660 661 |
static int copy_group_source_from_sockptr(struct group_source_req *greqs, sockptr_t optval, int optlen) |
b6238c04c net/ipv4: remove ... |
662 663 664 665 666 667 |
{ if (in_compat_syscall()) { struct compat_group_source_req gr32; if (optlen != sizeof(gr32)) return -EINVAL; |
89654c5fc net/ipv4: switch ... |
668 |
if (copy_from_sockptr(&gr32, optval, sizeof(gr32))) |
b6238c04c net/ipv4: remove ... |
669 670 671 672 673 674 675 |
return -EFAULT; greqs->gsr_interface = gr32.gsr_interface; greqs->gsr_group = gr32.gsr_group; greqs->gsr_source = gr32.gsr_source; } else { if (optlen != sizeof(*greqs)) return -EINVAL; |
89654c5fc net/ipv4: switch ... |
676 |
if (copy_from_sockptr(greqs, optval, sizeof(*greqs))) |
b6238c04c net/ipv4: remove ... |
677 678 679 680 681 |
return -EFAULT; } return 0; } |
2bbf8c1ea ipv4: take handli... |
682 |
static int do_mcast_group_source(struct sock *sk, int optname, |
89654c5fc net/ipv4: switch ... |
683 |
sockptr_t optval, int optlen) |
2bbf8c1ea ipv4: take handli... |
684 |
{ |
b6238c04c net/ipv4: remove ... |
685 |
struct group_source_req greqs; |
2bbf8c1ea ipv4: take handli... |
686 687 688 |
struct ip_mreq_source mreqs; struct sockaddr_in *psin; int omode, add, err; |
89654c5fc net/ipv4: switch ... |
689 |
err = copy_group_source_from_sockptr(&greqs, optval, optlen); |
b6238c04c net/ipv4: remove ... |
690 691 692 693 694 |
if (err) return err; if (greqs.gsr_group.ss_family != AF_INET || greqs.gsr_source.ss_family != AF_INET) |
2bbf8c1ea ipv4: take handli... |
695 |
return -EADDRNOTAVAIL; |
b6238c04c net/ipv4: remove ... |
696 |
psin = (struct sockaddr_in *)&greqs.gsr_group; |
2bbf8c1ea ipv4: take handli... |
697 |
mreqs.imr_multiaddr = psin->sin_addr.s_addr; |
b6238c04c net/ipv4: remove ... |
698 |
psin = (struct sockaddr_in *)&greqs.gsr_source; |
2bbf8c1ea ipv4: take handli... |
699 700 701 702 703 704 705 706 707 708 709 |
mreqs.imr_sourceaddr = psin->sin_addr.s_addr; mreqs.imr_interface = 0; /* use index for mc_source */ if (optname == MCAST_BLOCK_SOURCE) { omode = MCAST_EXCLUDE; add = 1; } else if (optname == MCAST_UNBLOCK_SOURCE) { omode = MCAST_EXCLUDE; add = 0; } else if (optname == MCAST_JOIN_SOURCE_GROUP) { struct ip_mreqn mreq; |
b6238c04c net/ipv4: remove ... |
710 |
psin = (struct sockaddr_in *)&greqs.gsr_group; |
2bbf8c1ea ipv4: take handli... |
711 712 |
mreq.imr_multiaddr = psin->sin_addr; mreq.imr_address.s_addr = 0; |
b6238c04c net/ipv4: remove ... |
713 |
mreq.imr_ifindex = greqs.gsr_interface; |
2bbf8c1ea ipv4: take handli... |
714 715 716 |
err = ip_mc_join_group_ssm(sk, &mreq, MCAST_INCLUDE); if (err && err != -EADDRINUSE) return err; |
b6238c04c net/ipv4: remove ... |
717 |
greqs.gsr_interface = mreq.imr_ifindex; |
2bbf8c1ea ipv4: take handli... |
718 719 720 721 722 723 |
omode = MCAST_INCLUDE; add = 1; } else /* MCAST_LEAVE_SOURCE_GROUP */ { omode = MCAST_INCLUDE; add = 0; } |
b6238c04c net/ipv4: remove ... |
724 |
return ip_mc_source(add, omode, sk, &mreqs, greqs.gsr_interface); |
2bbf8c1ea ipv4: take handli... |
725 |
} |
89654c5fc net/ipv4: switch ... |
726 |
static int ip_set_mcast_msfilter(struct sock *sk, sockptr_t optval, int optlen) |
d62c38f6a net/ipv4: factor ... |
727 728 729 730 731 732 733 734 |
{ struct group_filter *gsf = NULL; int err; if (optlen < GROUP_FILTER_SIZE(0)) return -EINVAL; if (optlen > sysctl_optmem_max) return -ENOBUFS; |
89654c5fc net/ipv4: switch ... |
735 |
gsf = memdup_sockptr(optval, optlen); |
d62c38f6a net/ipv4: factor ... |
736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 |
if (IS_ERR(gsf)) return PTR_ERR(gsf); /* numsrc >= (4G-140)/128 overflow in 32 bits */ err = -ENOBUFS; if (gsf->gf_numsrc >= 0x1ffffff || gsf->gf_numsrc > sock_net(sk)->ipv4.sysctl_igmp_max_msf) goto out_free_gsf; err = -EINVAL; if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) goto out_free_gsf; err = set_mcast_msfilter(sk, gsf->gf_interface, gsf->gf_numsrc, gsf->gf_fmode, &gsf->gf_group, gsf->gf_slist); out_free_gsf: kfree(gsf); return err; } |
89654c5fc net/ipv4: switch ... |
755 |
static int compat_ip_set_mcast_msfilter(struct sock *sk, sockptr_t optval, |
d62c38f6a net/ipv4: factor ... |
756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 |
int optlen) { const int size0 = offsetof(struct compat_group_filter, gf_slist); struct compat_group_filter *gf32; unsigned int n; void *p; int err; if (optlen < size0) return -EINVAL; if (optlen > sysctl_optmem_max - 4) return -ENOBUFS; p = kmalloc(optlen + 4, GFP_KERNEL); if (!p) return -ENOMEM; gf32 = p + 4; /* we want ->gf_group and ->gf_slist aligned */ err = -EFAULT; |
89654c5fc net/ipv4: switch ... |
775 |
if (copy_from_sockptr(gf32, optval, optlen)) |
d62c38f6a net/ipv4: factor ... |
776 777 778 779 780 781 782 783 784 785 786 |
goto out_free_gsf; /* numsrc >= (4G-140)/128 overflow in 32 bits */ n = gf32->gf_numsrc; err = -ENOBUFS; if (n >= 0x1ffffff) goto out_free_gsf; err = -EINVAL; if (offsetof(struct compat_group_filter, gf_slist[n]) > optlen) goto out_free_gsf; |
d62c38f6a net/ipv4: factor ... |
787 788 789 |
/* numsrc >= (4G-140)/128 overflow in 32 bits */ err = -ENOBUFS; if (n > sock_net(sk)->ipv4.sysctl_igmp_max_msf) |
b6238c04c net/ipv4: remove ... |
790 |
goto out_free_gsf; |
d62c38f6a net/ipv4: factor ... |
791 792 |
err = set_mcast_msfilter(sk, gf32->gf_interface, n, gf32->gf_fmode, &gf32->gf_group, gf32->gf_slist); |
d62c38f6a net/ipv4: factor ... |
793 794 795 796 |
out_free_gsf: kfree(p); return err; } |
d62c38f6a net/ipv4: factor ... |
797 |
|
02caad7cc net/ipv4: factor ... |
798 |
static int ip_mcast_join_leave(struct sock *sk, int optname, |
89654c5fc net/ipv4: switch ... |
799 |
sockptr_t optval, int optlen) |
02caad7cc net/ipv4: factor ... |
800 801 802 803 804 805 806 |
{ struct ip_mreqn mreq = { }; struct sockaddr_in *psin; struct group_req greq; if (optlen < sizeof(struct group_req)) return -EINVAL; |
89654c5fc net/ipv4: switch ... |
807 |
if (copy_from_sockptr(&greq, optval, sizeof(greq))) |
02caad7cc net/ipv4: factor ... |
808 809 810 811 812 813 814 815 816 817 818 |
return -EFAULT; psin = (struct sockaddr_in *)&greq.gr_group; if (psin->sin_family != AF_INET) return -EINVAL; mreq.imr_multiaddr = psin->sin_addr; mreq.imr_ifindex = greq.gr_interface; if (optname == MCAST_JOIN_GROUP) return ip_mc_join_group(sk, &mreq); return ip_mc_leave_group(sk, &mreq); } |
02caad7cc net/ipv4: factor ... |
819 |
static int compat_ip_mcast_join_leave(struct sock *sk, int optname, |
89654c5fc net/ipv4: switch ... |
820 |
sockptr_t optval, int optlen) |
02caad7cc net/ipv4: factor ... |
821 822 823 824 |
{ struct compat_group_req greq; struct ip_mreqn mreq = { }; struct sockaddr_in *psin; |
02caad7cc net/ipv4: factor ... |
825 826 827 |
if (optlen < sizeof(struct compat_group_req)) return -EINVAL; |
89654c5fc net/ipv4: switch ... |
828 |
if (copy_from_sockptr(&greq, optval, sizeof(greq))) |
02caad7cc net/ipv4: factor ... |
829 830 831 832 833 834 835 |
return -EFAULT; psin = (struct sockaddr_in *)&greq.gr_group; if (psin->sin_family != AF_INET) return -EINVAL; mreq.imr_multiaddr = psin->sin_addr; mreq.imr_ifindex = greq.gr_interface; |
02caad7cc net/ipv4: factor ... |
836 |
if (optname == MCAST_JOIN_GROUP) |
b6238c04c net/ipv4: remove ... |
837 838 |
return ip_mc_join_group(sk, &mreq); return ip_mc_leave_group(sk, &mreq); |
02caad7cc net/ipv4: factor ... |
839 |
} |
02caad7cc net/ipv4: factor ... |
840 |
|
89654c5fc net/ipv4: switch ... |
841 842 |
static int do_ip_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, unsigned int optlen) |
1da177e4c Linux-2.6.12-rc2 |
843 844 |
{ struct inet_sock *inet = inet_sk(sk); |
166b6b2d6 igmp: Namespaceif... |
845 |
struct net *net = sock_net(sk); |
09cb105ea net: clean up net... |
846 |
int val = 0, err; |
baf606d9c ipv4,ipv6: grab r... |
847 |
bool needs_rtnl = setsockopt_needs_rtnl(optname); |
1da177e4c Linux-2.6.12-rc2 |
848 |
|
0c9f79be2 ipv4: avoid undef... |
849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 |
switch (optname) { case IP_PKTINFO: case IP_RECVTTL: case IP_RECVOPTS: case IP_RECVTOS: case IP_RETOPTS: case IP_TOS: case IP_TTL: case IP_HDRINCL: case IP_MTU_DISCOVER: case IP_RECVERR: case IP_ROUTER_ALERT: case IP_FREEBIND: case IP_PASSSEC: case IP_TRANSPARENT: case IP_MINTTL: case IP_NODEFRAG: |
90c337da1 inet: add IP_BIND... |
866 |
case IP_BIND_ADDRESS_NO_PORT: |
0c9f79be2 ipv4: avoid undef... |
867 868 869 870 871 |
case IP_UNICAST_IF: case IP_MULTICAST_TTL: case IP_MULTICAST_ALL: case IP_MULTICAST_LOOP: case IP_RECVORIGDSTADDR: |
ad6f939ab ip: Add offset pa... |
872 |
case IP_CHECKSUM: |
70ecc2484 ipv4: add IP_RECV... |
873 |
case IP_RECVFRAGSIZE: |
eba75c587 icmp: support rfc... |
874 |
case IP_RECVERR_RFC4884: |
1da177e4c Linux-2.6.12-rc2 |
875 |
if (optlen >= sizeof(int)) { |
89654c5fc net/ipv4: switch ... |
876 |
if (copy_from_sockptr(&val, optval, sizeof(val))) |
1da177e4c Linux-2.6.12-rc2 |
877 878 879 |
return -EFAULT; } else if (optlen >= sizeof(char)) { unsigned char ucval; |
89654c5fc net/ipv4: switch ... |
880 |
if (copy_from_sockptr(&ucval, optval, sizeof(ucval))) |
1da177e4c Linux-2.6.12-rc2 |
881 882 883 884 885 886 |
return -EFAULT; val = (int) ucval; } } /* If optlen==0, it is equivalent to val == 0 */ |
0526947f9 net: Move IP_ROUT... |
887 888 |
if (optname == IP_ROUTER_ALERT) return ip_ra_control(sk, val ? 1 : 0, NULL); |
6a9fb9479 [IPV4]: Clean the... |
889 |
if (ip_mroute_opt(optname)) |
89654c5fc net/ipv4: switch ... |
890 |
return ip_mroute_setsockopt(sk, optname, optval, optlen); |
1da177e4c Linux-2.6.12-rc2 |
891 892 |
err = 0; |
baf606d9c ipv4,ipv6: grab r... |
893 894 |
if (needs_rtnl) rtnl_lock(); |
1da177e4c Linux-2.6.12-rc2 |
895 896 897 |
lock_sock(sk); switch (optname) { |
132adf546 [IPV4]: cleanup |
898 899 |
case IP_OPTIONS: { |
f6d8bd051 inet: add RCU pro... |
900 |
struct ip_options_rcu *old, *opt = NULL; |
65a1c4fff net: Cleanup redu... |
901 |
if (optlen > 40) |
132adf546 [IPV4]: cleanup |
902 |
goto e_inval; |
89654c5fc net/ipv4: switch ... |
903 |
err = ip_options_get(sock_net(sk), &opt, optval, optlen); |
132adf546 [IPV4]: cleanup |
904 905 |
if (err) break; |
f6d8bd051 inet: add RCU pro... |
906 |
old = rcu_dereference_protected(inet->inet_opt, |
1e1d04e67 net: introduce lo... |
907 |
lockdep_sock_is_held(sk)); |
132adf546 [IPV4]: cleanup |
908 909 |
if (inet->is_icsk) { struct inet_connection_sock *icsk = inet_csk(sk); |
dfd56b8b3 net: use IS_ENABL... |
910 |
#if IS_ENABLED(CONFIG_IPV6) |
132adf546 [IPV4]: cleanup |
911 912 913 |
if (sk->sk_family == PF_INET || (!((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) && |
c720c7e83 inet: rename some... |
914 |
inet->inet_daddr != LOOPBACK4_IPV6)) { |
1da177e4c Linux-2.6.12-rc2 |
915 |
#endif |
f6d8bd051 inet: add RCU pro... |
916 917 |
if (old) icsk->icsk_ext_hdr_len -= old->opt.optlen; |
132adf546 [IPV4]: cleanup |
918 |
if (opt) |
f6d8bd051 inet: add RCU pro... |
919 |
icsk->icsk_ext_hdr_len += opt->opt.optlen; |
132adf546 [IPV4]: cleanup |
920 |
icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); |
dfd56b8b3 net: use IS_ENABL... |
921 |
#if IS_ENABLED(CONFIG_IPV6) |
1da177e4c Linux-2.6.12-rc2 |
922 |
} |
132adf546 [IPV4]: cleanup |
923 |
#endif |
1da177e4c Linux-2.6.12-rc2 |
924 |
} |
f6d8bd051 inet: add RCU pro... |
925 926 |
rcu_assign_pointer(inet->inet_opt, opt); if (old) |
605b4afec ipv4: Convert cal... |
927 |
kfree_rcu(old, rcu); |
132adf546 [IPV4]: cleanup |
928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 |
break; } case IP_PKTINFO: if (val) inet->cmsg_flags |= IP_CMSG_PKTINFO; else inet->cmsg_flags &= ~IP_CMSG_PKTINFO; break; case IP_RECVTTL: if (val) inet->cmsg_flags |= IP_CMSG_TTL; else inet->cmsg_flags &= ~IP_CMSG_TTL; break; case IP_RECVTOS: if (val) inet->cmsg_flags |= IP_CMSG_TOS; else inet->cmsg_flags &= ~IP_CMSG_TOS; break; case IP_RECVOPTS: if (val) inet->cmsg_flags |= IP_CMSG_RECVOPTS; else inet->cmsg_flags &= ~IP_CMSG_RECVOPTS; break; case IP_RETOPTS: if (val) inet->cmsg_flags |= IP_CMSG_RETOPTS; else inet->cmsg_flags &= ~IP_CMSG_RETOPTS; break; case IP_PASSSEC: if (val) inet->cmsg_flags |= IP_CMSG_PASSSEC; else inet->cmsg_flags &= ~IP_CMSG_PASSSEC; break; |
e8b2dfe9b TPROXY: implement... |
966 967 968 969 970 971 |
case IP_RECVORIGDSTADDR: if (val) inet->cmsg_flags |= IP_CMSG_ORIGDSTADDR; else inet->cmsg_flags &= ~IP_CMSG_ORIGDSTADDR; break; |
ad6f939ab ip: Add offset pa... |
972 973 974 975 976 977 978 979 980 981 982 983 984 |
case IP_CHECKSUM: if (val) { if (!(inet->cmsg_flags & IP_CMSG_CHECKSUM)) { inet_inc_convert_csum(sk); inet->cmsg_flags |= IP_CMSG_CHECKSUM; } } else { if (inet->cmsg_flags & IP_CMSG_CHECKSUM) { inet_dec_convert_csum(sk); inet->cmsg_flags &= ~IP_CMSG_CHECKSUM; } } break; |
70ecc2484 ipv4: add IP_RECV... |
985 986 987 988 989 990 991 992 |
case IP_RECVFRAGSIZE: if (sk->sk_type != SOCK_RAW && sk->sk_type != SOCK_DGRAM) goto e_inval; if (val) inet->cmsg_flags |= IP_CMSG_RECVFRAGSIZE; else inet->cmsg_flags &= ~IP_CMSG_RECVFRAGSIZE; break; |
132adf546 [IPV4]: cleanup |
993 |
case IP_TOS: /* This sets both TOS and Precedence */ |
6ebf71bab ipv4: add ip_sock... |
994 |
__ip_sock_set_tos(sk, val); |
132adf546 [IPV4]: cleanup |
995 996 |
break; case IP_TTL: |
4d52cfbef net: ipv4/ip_sock... |
997 |
if (optlen < 1) |
132adf546 [IPV4]: cleanup |
998 |
goto e_inval; |
c9be4a5c4 net: prevent sett... |
999 |
if (val != -1 && (val < 1 || val > 255)) |
132adf546 [IPV4]: cleanup |
1000 1001 1002 1003 1004 1005 |
goto e_inval; inet->uc_ttl = val; break; case IP_HDRINCL: if (sk->sk_type != SOCK_RAW) { err = -ENOPROTOOPT; |
2c7946a7b [SECURITY]: TCP/U... |
1006 |
break; |
132adf546 [IPV4]: cleanup |
1007 1008 1009 |
} inet->hdrincl = val ? 1 : 0; break; |
7b2ff18ee net - IP_NODEFRAG... |
1010 1011 1012 1013 1014 1015 1016 |
case IP_NODEFRAG: if (sk->sk_type != SOCK_RAW) { err = -ENOPROTOOPT; break; } inet->nodefrag = val ? 1 : 0; break; |
90c337da1 inet: add IP_BIND... |
1017 1018 1019 |
case IP_BIND_ADDRESS_NO_PORT: inet->bind_address_no_port = val ? 1 : 0; break; |
132adf546 [IPV4]: cleanup |
1020 |
case IP_MTU_DISCOVER: |
1b3465763 ipv4: yet another... |
1021 |
if (val < IP_PMTUDISC_DONT || val > IP_PMTUDISC_OMIT) |
132adf546 [IPV4]: cleanup |
1022 1023 1024 1025 1026 1027 1028 1029 |
goto e_inval; inet->pmtudisc = val; break; case IP_RECVERR: inet->recverr = !!val; if (!val) skb_queue_purge(&sk->sk_error_queue); break; |
eba75c587 icmp: support rfc... |
1030 1031 1032 1033 1034 |
case IP_RECVERR_RFC4884: if (val < 0 || val > 1) goto e_inval; inet->recverr_rfc4884 = !!val; break; |
132adf546 [IPV4]: cleanup |
1035 1036 1037 |
case IP_MULTICAST_TTL: if (sk->sk_type == SOCK_STREAM) goto e_inval; |
4d52cfbef net: ipv4/ip_sock... |
1038 |
if (optlen < 1) |
132adf546 [IPV4]: cleanup |
1039 |
goto e_inval; |
09cb105ea net: clean up net... |
1040 |
if (val == -1) |
132adf546 [IPV4]: cleanup |
1041 1042 1043 1044 1045 1046 |
val = 1; if (val < 0 || val > 255) goto e_inval; inet->mc_ttl = val; break; case IP_MULTICAST_LOOP: |
4d52cfbef net: ipv4/ip_sock... |
1047 |
if (optlen < 1) |
132adf546 [IPV4]: cleanup |
1048 1049 1050 |
goto e_inval; inet->mc_loop = !!val; break; |
76e21053b ipv4: Implement I... |
1051 1052 1053 1054 |
case IP_UNICAST_IF: { struct net_device *dev = NULL; int ifindex; |
9515a2e08 net/ipv4: Allow s... |
1055 |
int midx; |
76e21053b ipv4: Implement I... |
1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 |
if (optlen != sizeof(int)) goto e_inval; ifindex = (__force int)ntohl((__force __be32)val); if (ifindex == 0) { inet->uc_index = 0; err = 0; break; } dev = dev_get_by_index(sock_net(sk), ifindex); err = -EADDRNOTAVAIL; if (!dev) break; |
9515a2e08 net/ipv4: Allow s... |
1071 1072 |
midx = l3mdev_master_ifindex(dev); |
76e21053b ipv4: Implement I... |
1073 1074 1075 |
dev_put(dev); err = -EINVAL; |
fdf1923bf net: Remove dupli... |
1076 |
if (sk->sk_bound_dev_if && midx != sk->sk_bound_dev_if) |
76e21053b ipv4: Implement I... |
1077 1078 1079 1080 1081 1082 |
break; inet->uc_index = ifindex; err = 0; break; } |
132adf546 [IPV4]: cleanup |
1083 1084 1085 1086 |
case IP_MULTICAST_IF: { struct ip_mreqn mreq; struct net_device *dev = NULL; |
7bb387c5a net: Allow IP_MUL... |
1087 |
int midx; |
132adf546 [IPV4]: cleanup |
1088 1089 1090 1091 1092 1093 |
if (sk->sk_type == SOCK_STREAM) goto e_inval; /* * Check the arguments are allowable */ |
0915921bd ipv4: check optle... |
1094 1095 |
if (optlen < sizeof(struct in_addr)) goto e_inval; |
132adf546 [IPV4]: cleanup |
1096 1097 |
err = -EFAULT; if (optlen >= sizeof(struct ip_mreqn)) { |
89654c5fc net/ipv4: switch ... |
1098 |
if (copy_from_sockptr(&mreq, optval, sizeof(mreq))) |
1da177e4c Linux-2.6.12-rc2 |
1099 |
break; |
132adf546 [IPV4]: cleanup |
1100 1101 |
} else { memset(&mreq, 0, sizeof(mreq)); |
3a084ddb4 net: IP_MULTICAST... |
1102 |
if (optlen >= sizeof(struct ip_mreq)) { |
89654c5fc net/ipv4: switch ... |
1103 1104 |
if (copy_from_sockptr(&mreq, optval, sizeof(struct ip_mreq))) |
3a084ddb4 net: IP_MULTICAST... |
1105 1106 |
break; } else if (optlen >= sizeof(struct in_addr)) { |
89654c5fc net/ipv4: switch ... |
1107 1108 |
if (copy_from_sockptr(&mreq.imr_address, optval, sizeof(struct in_addr))) |
3a084ddb4 net: IP_MULTICAST... |
1109 1110 |
break; } |
132adf546 [IPV4]: cleanup |
1111 1112 1113 |
} if (!mreq.imr_ifindex) { |
e6f1cebf7 [NET] endianness ... |
1114 |
if (mreq.imr_address.s_addr == htonl(INADDR_ANY)) { |
132adf546 [IPV4]: cleanup |
1115 1116 1117 |
inet->mc_index = 0; inet->mc_addr = 0; err = 0; |
1da177e4c Linux-2.6.12-rc2 |
1118 1119 |
break; } |
3b1e0a655 [NET] NETNS: Omit... |
1120 |
dev = ip_dev_find(sock_net(sk), mreq.imr_address.s_addr); |
55b805035 net: Fix IP_MULTI... |
1121 |
if (dev) |
132adf546 [IPV4]: cleanup |
1122 |
mreq.imr_ifindex = dev->ifindex; |
132adf546 [IPV4]: cleanup |
1123 |
} else |
55b805035 net: Fix IP_MULTI... |
1124 |
dev = dev_get_by_index(sock_net(sk), mreq.imr_ifindex); |
1da177e4c Linux-2.6.12-rc2 |
1125 |
|
1da177e4c Linux-2.6.12-rc2 |
1126 |
|
132adf546 [IPV4]: cleanup |
1127 1128 1129 |
err = -EADDRNOTAVAIL; if (!dev) break; |
7bb387c5a net: Allow IP_MUL... |
1130 1131 |
midx = l3mdev_master_ifindex(dev); |
55b805035 net: Fix IP_MULTI... |
1132 |
dev_put(dev); |
132adf546 [IPV4]: cleanup |
1133 1134 1135 |
err = -EINVAL; if (sk->sk_bound_dev_if && |
7bb387c5a net: Allow IP_MUL... |
1136 |
mreq.imr_ifindex != sk->sk_bound_dev_if && |
fdf1923bf net: Remove dupli... |
1137 |
midx != sk->sk_bound_dev_if) |
132adf546 [IPV4]: cleanup |
1138 |
break; |
1da177e4c Linux-2.6.12-rc2 |
1139 |
|
132adf546 [IPV4]: cleanup |
1140 1141 1142 1143 1144 |
inet->mc_index = mreq.imr_ifindex; inet->mc_addr = mreq.imr_address.s_addr; err = 0; break; } |
1da177e4c Linux-2.6.12-rc2 |
1145 |
|
132adf546 [IPV4]: cleanup |
1146 1147 1148 1149 |
case IP_ADD_MEMBERSHIP: case IP_DROP_MEMBERSHIP: { struct ip_mreqn mreq; |
1da177e4c Linux-2.6.12-rc2 |
1150 |
|
a96fb49be [NET]: Fix IP_ADD... |
1151 1152 1153 |
err = -EPROTO; if (inet_sk(sk)->is_icsk) break; |
132adf546 [IPV4]: cleanup |
1154 1155 1156 1157 |
if (optlen < sizeof(struct ip_mreq)) goto e_inval; err = -EFAULT; if (optlen >= sizeof(struct ip_mreqn)) { |
89654c5fc net/ipv4: switch ... |
1158 |
if (copy_from_sockptr(&mreq, optval, sizeof(mreq))) |
1da177e4c Linux-2.6.12-rc2 |
1159 |
break; |
132adf546 [IPV4]: cleanup |
1160 1161 |
} else { memset(&mreq, 0, sizeof(mreq)); |
89654c5fc net/ipv4: switch ... |
1162 1163 |
if (copy_from_sockptr(&mreq, optval, sizeof(struct ip_mreq))) |
1da177e4c Linux-2.6.12-rc2 |
1164 |
break; |
132adf546 [IPV4]: cleanup |
1165 |
} |
1da177e4c Linux-2.6.12-rc2 |
1166 |
|
132adf546 [IPV4]: cleanup |
1167 |
if (optname == IP_ADD_MEMBERSHIP) |
54ff9ef36 ipv4, ipv6: kill ... |
1168 |
err = ip_mc_join_group(sk, &mreq); |
132adf546 [IPV4]: cleanup |
1169 |
else |
54ff9ef36 ipv4, ipv6: kill ... |
1170 |
err = ip_mc_leave_group(sk, &mreq); |
132adf546 [IPV4]: cleanup |
1171 1172 1173 1174 |
break; } case IP_MSFILTER: { |
132adf546 [IPV4]: cleanup |
1175 1176 1177 1178 1179 1180 |
struct ip_msfilter *msf; if (optlen < IP_MSFILTER_SIZE(0)) goto e_inval; if (optlen > sysctl_optmem_max) { err = -ENOBUFS; |
1da177e4c Linux-2.6.12-rc2 |
1181 1182 |
break; } |
89654c5fc net/ipv4: switch ... |
1183 |
msf = memdup_sockptr(optval, optlen); |
a2c841d94 do_ip_setsockopt(... |
1184 1185 |
if (IS_ERR(msf)) { err = PTR_ERR(msf); |
132adf546 [IPV4]: cleanup |
1186 1187 1188 1189 |
break; } /* numsrc >= (1G-4) overflow in 32 bits */ if (msf->imsf_numsrc >= 0x3ffffffcU || |
166b6b2d6 igmp: Namespaceif... |
1190 |
msf->imsf_numsrc > net->ipv4.sysctl_igmp_max_msf) { |
132adf546 [IPV4]: cleanup |
1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 |
kfree(msf); err = -ENOBUFS; break; } if (IP_MSFILTER_SIZE(msf->imsf_numsrc) > optlen) { kfree(msf); err = -EINVAL; break; } err = ip_mc_msfilter(sk, msf, 0); kfree(msf); break; } case IP_BLOCK_SOURCE: case IP_UNBLOCK_SOURCE: case IP_ADD_SOURCE_MEMBERSHIP: case IP_DROP_SOURCE_MEMBERSHIP: { struct ip_mreq_source mreqs; int omode, add; |
1da177e4c Linux-2.6.12-rc2 |
1211 |
|
132adf546 [IPV4]: cleanup |
1212 1213 |
if (optlen != sizeof(struct ip_mreq_source)) goto e_inval; |
89654c5fc net/ipv4: switch ... |
1214 |
if (copy_from_sockptr(&mreqs, optval, sizeof(mreqs))) { |
1da177e4c Linux-2.6.12-rc2 |
1215 |
err = -EFAULT; |
1da177e4c Linux-2.6.12-rc2 |
1216 1217 |
break; } |
132adf546 [IPV4]: cleanup |
1218 1219 1220 1221 1222 1223 1224 1225 |
if (optname == IP_BLOCK_SOURCE) { omode = MCAST_EXCLUDE; add = 1; } else if (optname == IP_UNBLOCK_SOURCE) { omode = MCAST_EXCLUDE; add = 0; } else if (optname == IP_ADD_SOURCE_MEMBERSHIP) { struct ip_mreqn mreq; |
1da177e4c Linux-2.6.12-rc2 |
1226 |
|
132adf546 [IPV4]: cleanup |
1227 1228 1229 |
mreq.imr_multiaddr.s_addr = mreqs.imr_multiaddr; mreq.imr_address.s_addr = mreqs.imr_interface; mreq.imr_ifindex = 0; |
6e2059b53 ipv4/igmp: init g... |
1230 |
err = ip_mc_join_group_ssm(sk, &mreq, MCAST_INCLUDE); |
132adf546 [IPV4]: cleanup |
1231 |
if (err && err != -EADDRINUSE) |
1da177e4c Linux-2.6.12-rc2 |
1232 |
break; |
132adf546 [IPV4]: cleanup |
1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 |
omode = MCAST_INCLUDE; add = 1; } else /* IP_DROP_SOURCE_MEMBERSHIP */ { omode = MCAST_INCLUDE; add = 0; } err = ip_mc_source(add, omode, sk, &mreqs, 0); break; } case MCAST_JOIN_GROUP: case MCAST_LEAVE_GROUP: |
b6238c04c net/ipv4: remove ... |
1244 1245 1246 1247 1248 |
if (in_compat_syscall()) err = compat_ip_mcast_join_leave(sk, optname, optval, optlen); else err = ip_mcast_join_leave(sk, optname, optval, optlen); |
132adf546 [IPV4]: cleanup |
1249 |
break; |
132adf546 [IPV4]: cleanup |
1250 1251 1252 1253 |
case MCAST_JOIN_SOURCE_GROUP: case MCAST_LEAVE_SOURCE_GROUP: case MCAST_BLOCK_SOURCE: case MCAST_UNBLOCK_SOURCE: |
b6238c04c net/ipv4: remove ... |
1254 |
err = do_mcast_group_source(sk, optname, optval, optlen); |
132adf546 [IPV4]: cleanup |
1255 |
break; |
132adf546 [IPV4]: cleanup |
1256 |
case MCAST_MSFILTER: |
b6238c04c net/ipv4: remove ... |
1257 1258 1259 1260 |
if (in_compat_syscall()) err = compat_ip_set_mcast_msfilter(sk, optval, optlen); else err = ip_set_mcast_msfilter(sk, optval, optlen); |
132adf546 [IPV4]: cleanup |
1261 |
break; |
f771bef98 ipv4: New multica... |
1262 1263 1264 1265 1266 1267 1268 |
case IP_MULTICAST_ALL: if (optlen < 1) goto e_inval; if (val != 0 && val != 1) goto e_inval; inet->mc_all = val; break; |
132adf546 [IPV4]: cleanup |
1269 1270 |
case IP_FREEBIND: |
4d52cfbef net: ipv4/ip_sock... |
1271 |
if (optlen < 1) |
132adf546 [IPV4]: cleanup |
1272 1273 1274 1275 1276 1277 1278 |
goto e_inval; inet->freebind = !!val; break; case IP_IPSEC_POLICY: case IP_XFRM_POLICY: err = -EPERM; |
52e804c6d net: Allow userns... |
1279 |
if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) |
1da177e4c Linux-2.6.12-rc2 |
1280 |
break; |
89654c5fc net/ipv4: switch ... |
1281 |
err = xfrm_user_policy(sk, optname, optval, optlen); |
132adf546 [IPV4]: cleanup |
1282 |
break; |
1da177e4c Linux-2.6.12-rc2 |
1283 |
|
f5715aea4 ipv4: Implement I... |
1284 |
case IP_TRANSPARENT: |
52e804c6d net: Allow userns... |
1285 1286 |
if (!!val && !ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) && !ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) { |
f5715aea4 ipv4: Implement I... |
1287 1288 1289 1290 1291 1292 1293 |
err = -EPERM; break; } if (optlen < 1) goto e_inval; inet->transparent = !!val; break; |
d218d1113 tcp: Generalized ... |
1294 1295 1296 1297 1298 1299 1300 |
case IP_MINTTL: if (optlen < 1) goto e_inval; if (val < 0 || val > 255) goto e_inval; inet->min_ttl = val; break; |
132adf546 [IPV4]: cleanup |
1301 1302 1303 |
default: err = -ENOPROTOOPT; break; |
1da177e4c Linux-2.6.12-rc2 |
1304 1305 |
} release_sock(sk); |
baf606d9c ipv4,ipv6: grab r... |
1306 1307 |
if (needs_rtnl) rtnl_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
1308 1309 1310 1311 |
return err; e_inval: release_sock(sk); |
baf606d9c ipv4,ipv6: grab r... |
1312 1313 |
if (needs_rtnl) rtnl_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
1314 1315 |
return -EINVAL; } |
f84af32cb net: ip_queue_rcv... |
1316 |
/** |
829ae9d61 net-timestamp: al... |
1317 |
* ipv4_pktinfo_prepare - transfer some info from rtable to skb |
f84af32cb net: ip_queue_rcv... |
1318 1319 1320 |
* @sk: socket * @skb: buffer * |
35ebf65e8 ipv4: Create and ... |
1321 1322 |
* To support IP_CMSG_PKTINFO option, we store rt_iif and specific * destination in skb->cb[] before dst drop. |
8e3bff96a net: more spellin... |
1323 |
* This way, receiver doesn't make cache line misses to read rtable. |
f84af32cb net: ip_queue_rcv... |
1324 |
*/ |
fbf8866d6 net: ipv4 only po... |
1325 |
void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb) |
f84af32cb net: ip_queue_rcv... |
1326 |
{ |
d826eb14e ipv4: PKTINFO doe... |
1327 |
struct in_pktinfo *pktinfo = PKTINFO_SKB_CB(skb); |
4b261c75a ipv6: make IPV6_R... |
1328 1329 |
bool prepare = (inet_sk(sk)->cmsg_flags & IP_CMSG_PKTINFO) || ipv6_sk_rxinfo(sk); |
d826eb14e ipv4: PKTINFO doe... |
1330 |
|
4b261c75a ipv6: make IPV6_R... |
1331 |
if (prepare && skb_rtable(skb)) { |
0b922b7a8 net: original ing... |
1332 1333 1334 1335 |
/* skb->cb is overloaded: prior to this point it is IP{6}CB * which has interface index (iif) as the first member of the * underlying inet{6}_skb_parm struct. This code then overlays * PKTINFO_SKB_CB and in_pktinfo also has iif as the first |
f0c16ba89 net: fix incorrec... |
1336 1337 1338 1339 |
* element so the iif is picked up from the prior IPCB. If iif * is the loopback interface, then return the sending interface * (e.g., process binds socket to eth0 for Tx which is * redirected to loopback in the rtable/dst). |
0b922b7a8 net: original ing... |
1340 |
*/ |
cbea8f020 net: ipv4: fix l3... |
1341 1342 1343 1344 |
struct rtable *rt = skb_rtable(skb); bool l3slave = ipv4_l3mdev_skb(IPCB(skb)->flags); if (pktinfo->ipi_ifindex == LOOPBACK_IFINDEX) |
f0c16ba89 net: fix incorrec... |
1345 |
pktinfo->ipi_ifindex = inet_iif(skb); |
cbea8f020 net: ipv4: fix l3... |
1346 1347 |
else if (l3slave && rt && rt->rt_iif) pktinfo->ipi_ifindex = rt->rt_iif; |
f0c16ba89 net: fix incorrec... |
1348 |
|
35ebf65e8 ipv4: Create and ... |
1349 |
pktinfo->ipi_spec_dst.s_addr = fib_compute_spec_dst(skb); |
d826eb14e ipv4: PKTINFO doe... |
1350 1351 1352 1353 |
} else { pktinfo->ipi_ifindex = 0; pktinfo->ipi_spec_dst.s_addr = 0; } |
61a1030ba Revert "ipv4: kee... |
1354 |
skb_dst_drop(skb); |
f84af32cb net: ip_queue_rcv... |
1355 |
} |
f84af32cb net: ip_queue_rcv... |
1356 |
|
a7b75c5a8 net: pass a sockp... |
1357 1358 |
int ip_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, unsigned int optlen) |
3fdadf7d2 [NET]: {get|set}s... |
1359 1360 1361 1362 1363 |
{ int err; if (level != SOL_IP) return -ENOPROTOOPT; |
a7b75c5a8 net: pass a sockp... |
1364 |
err = do_ip_setsockopt(sk, level, optname, optval, optlen); |
97adaddaa net: bpfilter: fi... |
1365 |
#if IS_ENABLED(CONFIG_BPFILTER_UMH) |
d2ba09c17 net: add skeleton... |
1366 1367 |
if (optname >= BPFILTER_IPT_SO_SET_REPLACE && optname < BPFILTER_IPT_SET_MAX) |
a7b75c5a8 net: pass a sockp... |
1368 |
err = bpfilter_ip_set_sockopt(sk, optname, optval, optlen); |
d2ba09c17 net: add skeleton... |
1369 |
#endif |
3fdadf7d2 [NET]: {get|set}s... |
1370 1371 1372 |
#ifdef CONFIG_NETFILTER /* we need to exclude all possible ENOPROTOOPTs except default case */ if (err == -ENOPROTOOPT && optname != IP_HDRINCL && |
6a9fb9479 [IPV4]: Clean the... |
1373 1374 |
optname != IP_IPSEC_POLICY && optname != IP_XFRM_POLICY && |
3f34cfae1 netfilter: on soc... |
1375 |
!ip_mroute_opt(optname)) |
a7b75c5a8 net: pass a sockp... |
1376 |
err = nf_setsockopt(sk, PF_INET, optname, optval, optlen); |
3fdadf7d2 [NET]: {get|set}s... |
1377 1378 1379 |
#endif return err; } |
4d52cfbef net: ipv4/ip_sock... |
1380 |
EXPORT_SYMBOL(ip_setsockopt); |
3fdadf7d2 [NET]: {get|set}s... |
1381 |
|
1da177e4c Linux-2.6.12-rc2 |
1382 |
/* |
4d52cfbef net: ipv4/ip_sock... |
1383 1384 |
* Get the options. Note for future reference. The GET of IP options gets * the _received_ ones. The set sets the _sent_ ones. |
1da177e4c Linux-2.6.12-rc2 |
1385 |
*/ |
87e9f0315 ipv4: fix a poten... |
1386 1387 1388 1389 1390 1391 1392 1393 1394 |
static bool getsockopt_needs_rtnl(int optname) { switch (optname) { case IP_MSFILTER: case MCAST_MSFILTER: return true; } return false; } |
49e74c24f net/ipv4: factor ... |
1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 |
static int ip_get_mcast_msfilter(struct sock *sk, void __user *optval, int __user *optlen, int len) { const int size0 = offsetof(struct group_filter, gf_slist); struct group_filter __user *p = optval; struct group_filter gsf; int num; int err; if (len < size0) return -EINVAL; if (copy_from_user(&gsf, p, size0)) return -EFAULT; num = gsf.gf_numsrc; err = ip_mc_gsfget(sk, &gsf, p->gf_slist); if (err) return err; if (gsf.gf_numsrc < num) num = gsf.gf_numsrc; if (put_user(GROUP_FILTER_SIZE(num), optlen) || copy_to_user(p, &gsf, size0)) return -EFAULT; return 0; } |
49e74c24f net/ipv4: factor ... |
1420 |
static int compat_ip_get_mcast_msfilter(struct sock *sk, void __user *optval, |
b6238c04c net/ipv4: remove ... |
1421 |
int __user *optlen, int len) |
49e74c24f net/ipv4: factor ... |
1422 1423 1424 1425 1426 |
{ const int size0 = offsetof(struct compat_group_filter, gf_slist); struct compat_group_filter __user *p = optval; struct compat_group_filter gf32; struct group_filter gf; |
49e74c24f net/ipv4: factor ... |
1427 |
int num; |
b6238c04c net/ipv4: remove ... |
1428 |
int err; |
49e74c24f net/ipv4: factor ... |
1429 |
|
49e74c24f net/ipv4: factor ... |
1430 1431 |
if (len < size0) return -EINVAL; |
49e74c24f net/ipv4: factor ... |
1432 1433 1434 1435 1436 1437 1438 |
if (copy_from_user(&gf32, p, size0)) return -EFAULT; gf.gf_interface = gf32.gf_interface; gf.gf_fmode = gf32.gf_fmode; num = gf.gf_numsrc = gf32.gf_numsrc; gf.gf_group = gf32.gf_group; |
49e74c24f net/ipv4: factor ... |
1439 |
err = ip_mc_gsfget(sk, &gf, p->gf_slist); |
49e74c24f net/ipv4: factor ... |
1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 |
if (err) return err; if (gf.gf_numsrc < num) num = gf.gf_numsrc; len = GROUP_FILTER_SIZE(num) - (sizeof(gf) - sizeof(gf32)); if (put_user(len, optlen) || put_user(gf.gf_fmode, &p->gf_fmode) || put_user(gf.gf_numsrc, &p->gf_numsrc)) return -EFAULT; return 0; } |
49e74c24f net/ipv4: factor ... |
1451 |
|
3fdadf7d2 [NET]: {get|set}s... |
1452 |
static int do_ip_getsockopt(struct sock *sk, int level, int optname, |
b6238c04c net/ipv4: remove ... |
1453 |
char __user *optval, int __user *optlen) |
1da177e4c Linux-2.6.12-rc2 |
1454 1455 |
{ struct inet_sock *inet = inet_sk(sk); |
87e9f0315 ipv4: fix a poten... |
1456 1457 |
bool needs_rtnl = getsockopt_needs_rtnl(optname); int val, err = 0; |
1da177e4c Linux-2.6.12-rc2 |
1458 |
int len; |
e905a9eda [NET] IPV4: Fix w... |
1459 |
|
132adf546 [IPV4]: cleanup |
1460 |
if (level != SOL_IP) |
1da177e4c Linux-2.6.12-rc2 |
1461 |
return -EOPNOTSUPP; |
6a9fb9479 [IPV4]: Clean the... |
1462 |
if (ip_mroute_opt(optname)) |
09cb105ea net: clean up net... |
1463 |
return ip_mroute_getsockopt(sk, optname, optval, optlen); |
1da177e4c Linux-2.6.12-rc2 |
1464 |
|
09cb105ea net: clean up net... |
1465 |
if (get_user(len, optlen)) |
1da177e4c Linux-2.6.12-rc2 |
1466 |
return -EFAULT; |
132adf546 [IPV4]: cleanup |
1467 |
if (len < 0) |
1da177e4c Linux-2.6.12-rc2 |
1468 |
return -EINVAL; |
e905a9eda [NET] IPV4: Fix w... |
1469 |
|
87e9f0315 ipv4: fix a poten... |
1470 1471 |
if (needs_rtnl) rtnl_lock(); |
1da177e4c Linux-2.6.12-rc2 |
1472 |
lock_sock(sk); |
132adf546 [IPV4]: cleanup |
1473 1474 1475 1476 |
switch (optname) { case IP_OPTIONS: { unsigned char optbuf[sizeof(struct ip_options)+40]; |
f6d8bd051 inet: add RCU pro... |
1477 1478 1479 1480 |
struct ip_options *opt = (struct ip_options *)optbuf; struct ip_options_rcu *inet_opt; inet_opt = rcu_dereference_protected(inet->inet_opt, |
1e1d04e67 net: introduce lo... |
1481 |
lockdep_sock_is_held(sk)); |
132adf546 [IPV4]: cleanup |
1482 |
opt->optlen = 0; |
f6d8bd051 inet: add RCU pro... |
1483 1484 1485 1486 |
if (inet_opt) memcpy(optbuf, &inet_opt->opt, sizeof(struct ip_options) + inet_opt->opt.optlen); |
132adf546 [IPV4]: cleanup |
1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 |
release_sock(sk); if (opt->optlen == 0) return put_user(0, optlen); ip_options_undo(opt); len = min_t(unsigned int, len, opt->optlen); if (put_user(len, optlen)) return -EFAULT; if (copy_to_user(optval, opt->__data, len)) return -EFAULT; return 0; } case IP_PKTINFO: val = (inet->cmsg_flags & IP_CMSG_PKTINFO) != 0; break; case IP_RECVTTL: val = (inet->cmsg_flags & IP_CMSG_TTL) != 0; break; case IP_RECVTOS: val = (inet->cmsg_flags & IP_CMSG_TOS) != 0; break; case IP_RECVOPTS: val = (inet->cmsg_flags & IP_CMSG_RECVOPTS) != 0; break; case IP_RETOPTS: val = (inet->cmsg_flags & IP_CMSG_RETOPTS) != 0; break; case IP_PASSSEC: val = (inet->cmsg_flags & IP_CMSG_PASSSEC) != 0; break; |
e8b2dfe9b TPROXY: implement... |
1519 1520 1521 |
case IP_RECVORIGDSTADDR: val = (inet->cmsg_flags & IP_CMSG_ORIGDSTADDR) != 0; break; |
ad6f939ab ip: Add offset pa... |
1522 1523 1524 |
case IP_CHECKSUM: val = (inet->cmsg_flags & IP_CMSG_CHECKSUM) != 0; break; |
70ecc2484 ipv4: add IP_RECV... |
1525 1526 1527 |
case IP_RECVFRAGSIZE: val = (inet->cmsg_flags & IP_CMSG_RECVFRAGSIZE) != 0; break; |
132adf546 [IPV4]: cleanup |
1528 1529 1530 1531 |
case IP_TOS: val = inet->tos; break; case IP_TTL: |
fa50d974d ipv4: Namespaceif... |
1532 1533 |
{ struct net *net = sock_net(sk); |
132adf546 [IPV4]: cleanup |
1534 |
val = (inet->uc_ttl == -1 ? |
fa50d974d ipv4: Namespaceif... |
1535 |
net->ipv4.sysctl_ip_default_ttl : |
132adf546 [IPV4]: cleanup |
1536 1537 |
inet->uc_ttl); break; |
fa50d974d ipv4: Namespaceif... |
1538 |
} |
132adf546 [IPV4]: cleanup |
1539 1540 1541 |
case IP_HDRINCL: val = inet->hdrincl; break; |
a89b47639 ipv4: enable gets... |
1542 1543 1544 |
case IP_NODEFRAG: val = inet->nodefrag; break; |
90c337da1 inet: add IP_BIND... |
1545 1546 1547 |
case IP_BIND_ADDRESS_NO_PORT: val = inet->bind_address_no_port; break; |
132adf546 [IPV4]: cleanup |
1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 |
case IP_MTU_DISCOVER: val = inet->pmtudisc; break; case IP_MTU: { struct dst_entry *dst; val = 0; dst = sk_dst_get(sk); if (dst) { val = dst_mtu(dst); dst_release(dst); |
1da177e4c Linux-2.6.12-rc2 |
1559 |
} |
132adf546 [IPV4]: cleanup |
1560 |
if (!val) { |
1da177e4c Linux-2.6.12-rc2 |
1561 |
release_sock(sk); |
132adf546 [IPV4]: cleanup |
1562 |
return -ENOTCONN; |
1da177e4c Linux-2.6.12-rc2 |
1563 |
} |
132adf546 [IPV4]: cleanup |
1564 1565 1566 1567 1568 |
break; } case IP_RECVERR: val = inet->recverr; break; |
eba75c587 icmp: support rfc... |
1569 1570 1571 |
case IP_RECVERR_RFC4884: val = inet->recverr_rfc4884; break; |
132adf546 [IPV4]: cleanup |
1572 1573 1574 1575 1576 1577 |
case IP_MULTICAST_TTL: val = inet->mc_ttl; break; case IP_MULTICAST_LOOP: val = inet->mc_loop; break; |
76e21053b ipv4: Implement I... |
1578 1579 1580 |
case IP_UNICAST_IF: val = (__force int)htonl((__u32) inet->uc_index); break; |
132adf546 [IPV4]: cleanup |
1581 1582 1583 1584 1585 1586 |
case IP_MULTICAST_IF: { struct in_addr addr; len = min_t(unsigned int, len, sizeof(struct in_addr)); addr.s_addr = inet->mc_addr; release_sock(sk); |
1da177e4c Linux-2.6.12-rc2 |
1587 |
|
132adf546 [IPV4]: cleanup |
1588 1589 1590 1591 1592 1593 1594 1595 1596 |
if (put_user(len, optlen)) return -EFAULT; if (copy_to_user(optval, &addr, len)) return -EFAULT; return 0; } case IP_MSFILTER: { struct ip_msfilter msf; |
132adf546 [IPV4]: cleanup |
1597 1598 |
if (len < IP_MSFILTER_SIZE(0)) { |
87e9f0315 ipv4: fix a poten... |
1599 1600 |
err = -EINVAL; goto out; |
1da177e4c Linux-2.6.12-rc2 |
1601 |
} |
132adf546 [IPV4]: cleanup |
1602 |
if (copy_from_user(&msf, optval, IP_MSFILTER_SIZE(0))) { |
87e9f0315 ipv4: fix a poten... |
1603 1604 |
err = -EFAULT; goto out; |
1da177e4c Linux-2.6.12-rc2 |
1605 |
} |
132adf546 [IPV4]: cleanup |
1606 1607 |
err = ip_mc_msfget(sk, &msf, (struct ip_msfilter __user *)optval, optlen); |
87e9f0315 ipv4: fix a poten... |
1608 |
goto out; |
132adf546 [IPV4]: cleanup |
1609 1610 |
} case MCAST_MSFILTER: |
b6238c04c net/ipv4: remove ... |
1611 1612 1613 1614 1615 |
if (in_compat_syscall()) err = compat_ip_get_mcast_msfilter(sk, optval, optlen, len); else err = ip_get_mcast_msfilter(sk, optval, optlen, len); |
87e9f0315 ipv4: fix a poten... |
1616 |
goto out; |
f771bef98 ipv4: New multica... |
1617 1618 1619 |
case IP_MULTICAST_ALL: val = inet->mc_all; break; |
132adf546 [IPV4]: cleanup |
1620 1621 1622 |
case IP_PKTOPTIONS: { struct msghdr msg; |
1da177e4c Linux-2.6.12-rc2 |
1623 |
|
132adf546 [IPV4]: cleanup |
1624 |
release_sock(sk); |
1da177e4c Linux-2.6.12-rc2 |
1625 |
|
132adf546 [IPV4]: cleanup |
1626 1627 |
if (sk->sk_type != SOCK_STREAM) return -ENOPROTOOPT; |
1da177e4c Linux-2.6.12-rc2 |
1628 |
|
1f466e1f1 net: cleanly hand... |
1629 1630 |
msg.msg_control_is_user = true; msg.msg_control_user = optval; |
132adf546 [IPV4]: cleanup |
1631 |
msg.msg_controllen = len; |
b6238c04c net/ipv4: remove ... |
1632 |
msg.msg_flags = in_compat_syscall() ? MSG_CMSG_COMPAT : 0; |
1da177e4c Linux-2.6.12-rc2 |
1633 |
|
132adf546 [IPV4]: cleanup |
1634 1635 |
if (inet->cmsg_flags & IP_CMSG_PKTINFO) { struct in_pktinfo info; |
c720c7e83 inet: rename some... |
1636 1637 |
info.ipi_addr.s_addr = inet->inet_rcv_saddr; info.ipi_spec_dst.s_addr = inet->inet_rcv_saddr; |
132adf546 [IPV4]: cleanup |
1638 1639 |
info.ipi_ifindex = inet->mc_index; put_cmsg(&msg, SOL_IP, IP_PKTINFO, sizeof(info), &info); |
1da177e4c Linux-2.6.12-rc2 |
1640 |
} |
132adf546 [IPV4]: cleanup |
1641 1642 1643 1644 |
if (inet->cmsg_flags & IP_CMSG_TTL) { int hlim = inet->mc_ttl; put_cmsg(&msg, SOL_IP, IP_TTL, sizeof(hlim), &hlim); } |
4c507d289 net: implement IP... |
1645 1646 1647 1648 |
if (inet->cmsg_flags & IP_CMSG_TOS) { int tos = inet->rcv_tos; put_cmsg(&msg, SOL_IP, IP_TOS, sizeof(tos), &tos); } |
132adf546 [IPV4]: cleanup |
1649 1650 1651 1652 1653 1654 |
len -= msg.msg_controllen; return put_user(len, optlen); } case IP_FREEBIND: val = inet->freebind; break; |
f5715aea4 ipv4: Implement I... |
1655 1656 1657 |
case IP_TRANSPARENT: val = inet->transparent; break; |
d218d1113 tcp: Generalized ... |
1658 1659 1660 |
case IP_MINTTL: val = inet->min_ttl; break; |
132adf546 [IPV4]: cleanup |
1661 1662 1663 |
default: release_sock(sk); return -ENOPROTOOPT; |
1da177e4c Linux-2.6.12-rc2 |
1664 1665 |
} release_sock(sk); |
e905a9eda [NET] IPV4: Fix w... |
1666 |
|
4d52cfbef net: ipv4/ip_sock... |
1667 |
if (len < sizeof(int) && len > 0 && val >= 0 && val <= 255) { |
1da177e4c Linux-2.6.12-rc2 |
1668 1669 |
unsigned char ucval = (unsigned char)val; len = 1; |
132adf546 [IPV4]: cleanup |
1670 |
if (put_user(len, optlen)) |
1da177e4c Linux-2.6.12-rc2 |
1671 |
return -EFAULT; |
09cb105ea net: clean up net... |
1672 |
if (copy_to_user(optval, &ucval, 1)) |
1da177e4c Linux-2.6.12-rc2 |
1673 1674 1675 |
return -EFAULT; } else { len = min_t(unsigned int, sizeof(int), len); |
132adf546 [IPV4]: cleanup |
1676 |
if (put_user(len, optlen)) |
1da177e4c Linux-2.6.12-rc2 |
1677 |
return -EFAULT; |
09cb105ea net: clean up net... |
1678 |
if (copy_to_user(optval, &val, len)) |
1da177e4c Linux-2.6.12-rc2 |
1679 1680 1681 |
return -EFAULT; } return 0; |
87e9f0315 ipv4: fix a poten... |
1682 1683 1684 1685 1686 1687 |
out: release_sock(sk); if (needs_rtnl) rtnl_unlock(); return err; |
1da177e4c Linux-2.6.12-rc2 |
1688 |
} |
3fdadf7d2 [NET]: {get|set}s... |
1689 |
int ip_getsockopt(struct sock *sk, int level, |
132adf546 [IPV4]: cleanup |
1690 |
int optname, char __user *optval, int __user *optlen) |
3fdadf7d2 [NET]: {get|set}s... |
1691 1692 |
{ int err; |
b6238c04c net/ipv4: remove ... |
1693 |
err = do_ip_getsockopt(sk, level, optname, optval, optlen); |
42908c69f net: Add compat s... |
1694 |
|
97adaddaa net: bpfilter: fi... |
1695 |
#if IS_ENABLED(CONFIG_BPFILTER_UMH) |
d2ba09c17 net: add skeleton... |
1696 1697 1698 1699 |
if (optname >= BPFILTER_IPT_SO_GET_INFO && optname < BPFILTER_IPT_GET_MAX) err = bpfilter_ip_get_sockopt(sk, optname, optval, optlen); #endif |
3fdadf7d2 [NET]: {get|set}s... |
1700 1701 |
#ifdef CONFIG_NETFILTER /* we need to exclude all possible ENOPROTOOPTs except default case */ |
6a9fb9479 [IPV4]: Clean the... |
1702 1703 |
if (err == -ENOPROTOOPT && optname != IP_PKTOPTIONS && !ip_mroute_opt(optname)) { |
e905a9eda [NET] IPV4: Fix w... |
1704 |
int len; |
3fdadf7d2 [NET]: {get|set}s... |
1705 |
|
543d9cfee [NET]: Identation... |
1706 |
if (get_user(len, optlen)) |
3fdadf7d2 [NET]: {get|set}s... |
1707 |
return -EFAULT; |
77d4df41d netfilter: remove... |
1708 |
err = nf_getsockopt(sk, PF_INET, optname, optval, &len); |
3fdadf7d2 [NET]: {get|set}s... |
1709 1710 1711 1712 1713 1714 1715 |
if (err >= 0) err = put_user(len, optlen); return err; } #endif return err; } |
b6238c04c net/ipv4: remove ... |
1716 |
EXPORT_SYMBOL(ip_getsockopt); |