aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/raw.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/raw.c')
-rw-r--r--net/ipv4/raw.c120
1 files changed, 75 insertions, 45 deletions
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 009a7b2aa1ef..c9893d43242e 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -76,6 +76,7 @@
76#include <linux/seq_file.h> 76#include <linux/seq_file.h>
77#include <linux/netfilter.h> 77#include <linux/netfilter.h>
78#include <linux/netfilter_ipv4.h> 78#include <linux/netfilter_ipv4.h>
79#include <linux/compat.h>
79 80
80static struct raw_hashinfo raw_v4_hashinfo = { 81static struct raw_hashinfo raw_v4_hashinfo = {
81 .lock = __RW_LOCK_UNLOCKED(raw_v4_hashinfo.lock), 82 .lock = __RW_LOCK_UNLOCKED(raw_v4_hashinfo.lock),
@@ -153,7 +154,7 @@ static __inline__ int icmp_filter(struct sock *sk, struct sk_buff *skb)
153 * RFC 1122: SHOULD pass TOS value up to the transport layer. 154 * RFC 1122: SHOULD pass TOS value up to the transport layer.
154 * -> It does. And not only TOS, but all IP header. 155 * -> It does. And not only TOS, but all IP header.
155 */ 156 */
156static int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash) 157static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash)
157{ 158{
158 struct sock *sk; 159 struct sock *sk;
159 struct hlist_head *head; 160 struct hlist_head *head;
@@ -246,7 +247,7 @@ static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info)
246 } 247 }
247 248
248 if (inet->recverr) { 249 if (inet->recverr) {
249 struct iphdr *iph = (struct iphdr *)skb->data; 250 const struct iphdr *iph = (const struct iphdr *)skb->data;
250 u8 *payload = skb->data + (iph->ihl << 2); 251 u8 *payload = skb->data + (iph->ihl << 2);
251 252
252 if (inet->hdrincl) 253 if (inet->hdrincl)
@@ -264,7 +265,7 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info)
264{ 265{
265 int hash; 266 int hash;
266 struct sock *raw_sk; 267 struct sock *raw_sk;
267 struct iphdr *iph; 268 const struct iphdr *iph;
268 struct net *net; 269 struct net *net;
269 270
270 hash = protocol & (RAW_HTABLE_SIZE - 1); 271 hash = protocol & (RAW_HTABLE_SIZE - 1);
@@ -272,7 +273,7 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info)
272 read_lock(&raw_v4_hashinfo.lock); 273 read_lock(&raw_v4_hashinfo.lock);
273 raw_sk = sk_head(&raw_v4_hashinfo.ht[hash]); 274 raw_sk = sk_head(&raw_v4_hashinfo.ht[hash]);
274 if (raw_sk != NULL) { 275 if (raw_sk != NULL) {
275 iph = (struct iphdr *)skb->data; 276 iph = (const struct iphdr *)skb->data;
276 net = dev_net(skb->dev); 277 net = dev_net(skb->dev);
277 278
278 while ((raw_sk = __raw_v4_lookup(net, raw_sk, protocol, 279 while ((raw_sk = __raw_v4_lookup(net, raw_sk, protocol,
@@ -280,7 +281,7 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info)
280 skb->dev->ifindex)) != NULL) { 281 skb->dev->ifindex)) != NULL) {
281 raw_err(raw_sk, skb, info); 282 raw_err(raw_sk, skb, info);
282 raw_sk = sk_next(raw_sk); 283 raw_sk = sk_next(raw_sk);
283 iph = (struct iphdr *)skb->data; 284 iph = (const struct iphdr *)skb->data;
284 } 285 }
285 } 286 }
286 read_unlock(&raw_v4_hashinfo.lock); 287 read_unlock(&raw_v4_hashinfo.lock);
@@ -313,9 +314,10 @@ int raw_rcv(struct sock *sk, struct sk_buff *skb)
313 return 0; 314 return 0;
314} 315}
315 316
316static int raw_send_hdrinc(struct sock *sk, void *from, size_t length, 317static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
317 struct rtable **rtp, 318 void *from, size_t length,
318 unsigned int flags) 319 struct rtable **rtp,
320 unsigned int flags)
319{ 321{
320 struct inet_sock *inet = inet_sk(sk); 322 struct inet_sock *inet = inet_sk(sk);
321 struct net *net = sock_net(sk); 323 struct net *net = sock_net(sk);
@@ -326,7 +328,7 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length,
326 struct rtable *rt = *rtp; 328 struct rtable *rt = *rtp;
327 329
328 if (length > rt->dst.dev->mtu) { 330 if (length > rt->dst.dev->mtu) {
329 ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->inet_dport, 331 ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport,
330 rt->dst.dev->mtu); 332 rt->dst.dev->mtu);
331 return -EMSGSIZE; 333 return -EMSGSIZE;
332 } 334 }
@@ -371,7 +373,7 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length,
371 373
372 if (iphlen >= sizeof(*iph)) { 374 if (iphlen >= sizeof(*iph)) {
373 if (!iph->saddr) 375 if (!iph->saddr)
374 iph->saddr = rt->rt_src; 376 iph->saddr = fl4->saddr;
375 iph->check = 0; 377 iph->check = 0;
376 iph->tot_len = htons(length); 378 iph->tot_len = htons(length);
377 if (!iph->id) 379 if (!iph->id)
@@ -401,7 +403,7 @@ error:
401 return err; 403 return err;
402} 404}
403 405
404static int raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg) 406static int raw_probe_proto_opt(struct flowi4 *fl4, struct msghdr *msg)
405{ 407{
406 struct iovec *iov; 408 struct iovec *iov;
407 u8 __user *type = NULL; 409 u8 __user *type = NULL;
@@ -417,7 +419,7 @@ static int raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
417 if (!iov) 419 if (!iov)
418 continue; 420 continue;
419 421
420 switch (fl->proto) { 422 switch (fl4->flowi4_proto) {
421 case IPPROTO_ICMP: 423 case IPPROTO_ICMP:
422 /* check if one-byte field is readable or not. */ 424 /* check if one-byte field is readable or not. */
423 if (iov->iov_base && iov->iov_len < 1) 425 if (iov->iov_base && iov->iov_len < 1)
@@ -432,8 +434,8 @@ static int raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
432 code = iov->iov_base; 434 code = iov->iov_base;
433 435
434 if (type && code) { 436 if (type && code) {
435 if (get_user(fl->fl_icmp_type, type) || 437 if (get_user(fl4->fl4_icmp_type, type) ||
436 get_user(fl->fl_icmp_code, code)) 438 get_user(fl4->fl4_icmp_code, code))
437 return -EFAULT; 439 return -EFAULT;
438 probed = 1; 440 probed = 1;
439 } 441 }
@@ -454,11 +456,13 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
454 struct inet_sock *inet = inet_sk(sk); 456 struct inet_sock *inet = inet_sk(sk);
455 struct ipcm_cookie ipc; 457 struct ipcm_cookie ipc;
456 struct rtable *rt = NULL; 458 struct rtable *rt = NULL;
459 struct flowi4 fl4;
457 int free = 0; 460 int free = 0;
458 __be32 daddr; 461 __be32 daddr;
459 __be32 saddr; 462 __be32 saddr;
460 u8 tos; 463 u8 tos;
461 int err; 464 int err;
465 struct ip_options_data opt_copy;
462 466
463 err = -EMSGSIZE; 467 err = -EMSGSIZE;
464 if (len > 0xFFFF) 468 if (len > 0xFFFF)
@@ -505,7 +509,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
505 509
506 ipc.addr = inet->inet_saddr; 510 ipc.addr = inet->inet_saddr;
507 ipc.opt = NULL; 511 ipc.opt = NULL;
508 ipc.shtx.flags = 0; 512 ipc.tx_flags = 0;
509 ipc.oif = sk->sk_bound_dev_if; 513 ipc.oif = sk->sk_bound_dev_if;
510 514
511 if (msg->msg_controllen) { 515 if (msg->msg_controllen) {
@@ -519,8 +523,18 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
519 saddr = ipc.addr; 523 saddr = ipc.addr;
520 ipc.addr = daddr; 524 ipc.addr = daddr;
521 525
522 if (!ipc.opt) 526 if (!ipc.opt) {
523 ipc.opt = inet->opt; 527 struct ip_options_rcu *inet_opt;
528
529 rcu_read_lock();
530 inet_opt = rcu_dereference(inet->inet_opt);
531 if (inet_opt) {
532 memcpy(&opt_copy, inet_opt,
533 sizeof(*inet_opt) + inet_opt->opt.optlen);
534 ipc.opt = &opt_copy.opt;
535 }
536 rcu_read_unlock();
537 }
524 538
525 if (ipc.opt) { 539 if (ipc.opt) {
526 err = -EINVAL; 540 err = -EINVAL;
@@ -529,10 +543,10 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
529 */ 543 */
530 if (inet->hdrincl) 544 if (inet->hdrincl)
531 goto done; 545 goto done;
532 if (ipc.opt->srr) { 546 if (ipc.opt->opt.srr) {
533 if (!daddr) 547 if (!daddr)
534 goto done; 548 goto done;
535 daddr = ipc.opt->faddr; 549 daddr = ipc.opt->opt.faddr;
536 } 550 }
537 } 551 }
538 tos = RT_CONN_FLAGS(sk); 552 tos = RT_CONN_FLAGS(sk);
@@ -546,27 +560,24 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
546 saddr = inet->mc_addr; 560 saddr = inet->mc_addr;
547 } 561 }
548 562
549 { 563 flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,
550 struct flowi fl = { .oif = ipc.oif, 564 RT_SCOPE_UNIVERSE,
551 .mark = sk->sk_mark, 565 inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
552 .nl_u = { .ip4_u = 566 FLOWI_FLAG_CAN_SLEEP, daddr, saddr, 0, 0);
553 { .daddr = daddr,
554 .saddr = saddr,
555 .tos = tos } },
556 .proto = inet->hdrincl ? IPPROTO_RAW :
557 sk->sk_protocol,
558 };
559 if (!inet->hdrincl) {
560 err = raw_probe_proto_opt(&fl, msg);
561 if (err)
562 goto done;
563 }
564 567
565 security_sk_classify_flow(sk, &fl); 568 if (!inet->hdrincl) {
566 err = ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 1); 569 err = raw_probe_proto_opt(&fl4, msg);
570 if (err)
571 goto done;
567 } 572 }
568 if (err) 573
574 security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));
575 rt = ip_route_output_flow(sock_net(sk), &fl4, sk);
576 if (IS_ERR(rt)) {
577 err = PTR_ERR(rt);
578 rt = NULL;
569 goto done; 579 goto done;
580 }
570 581
571 err = -EACCES; 582 err = -EACCES;
572 if (rt->rt_flags & RTCF_BROADCAST && !sock_flag(sk, SOCK_BROADCAST)) 583 if (rt->rt_flags & RTCF_BROADCAST && !sock_flag(sk, SOCK_BROADCAST))
@@ -577,19 +588,20 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
577back_from_confirm: 588back_from_confirm:
578 589
579 if (inet->hdrincl) 590 if (inet->hdrincl)
580 err = raw_send_hdrinc(sk, msg->msg_iov, len, 591 err = raw_send_hdrinc(sk, &fl4, msg->msg_iov, len,
581 &rt, msg->msg_flags); 592 &rt, msg->msg_flags);
582 593
583 else { 594 else {
584 if (!ipc.addr) 595 if (!ipc.addr)
585 ipc.addr = rt->rt_dst; 596 ipc.addr = fl4.daddr;
586 lock_sock(sk); 597 lock_sock(sk);
587 err = ip_append_data(sk, ip_generic_getfrag, msg->msg_iov, len, 0, 598 err = ip_append_data(sk, &fl4, ip_generic_getfrag,
588 &ipc, &rt, msg->msg_flags); 599 msg->msg_iov, len, 0,
600 &ipc, &rt, msg->msg_flags);
589 if (err) 601 if (err)
590 ip_flush_pending_frames(sk); 602 ip_flush_pending_frames(sk);
591 else if (!(msg->msg_flags & MSG_MORE)) { 603 else if (!(msg->msg_flags & MSG_MORE)) {
592 err = ip_push_pending_frames(sk); 604 err = ip_push_pending_frames(sk, &fl4);
593 if (err == -ENOBUFS && !inet->recverr) 605 if (err == -ENOBUFS && !inet->recverr)
594 err = 0; 606 err = 0;
595 } 607 }
@@ -616,7 +628,7 @@ do_confirm:
616static void raw_close(struct sock *sk, long timeout) 628static void raw_close(struct sock *sk, long timeout)
617{ 629{
618 /* 630 /*
619 * Raw sockets may have direct kernel refereneces. Kill them. 631 * Raw sockets may have direct kernel references. Kill them.
620 */ 632 */
621 ip_ra_control(sk, 0, NULL); 633 ip_ra_control(sk, 0, NULL);
622 634
@@ -839,6 +851,23 @@ static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
839 } 851 }
840} 852}
841 853
854#ifdef CONFIG_COMPAT
855static int compat_raw_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg)
856{
857 switch (cmd) {
858 case SIOCOUTQ:
859 case SIOCINQ:
860 return -ENOIOCTLCMD;
861 default:
862#ifdef CONFIG_IP_MROUTE
863 return ipmr_compat_ioctl(sk, cmd, compat_ptr(arg));
864#else
865 return -ENOIOCTLCMD;
866#endif
867 }
868}
869#endif
870
842struct proto raw_prot = { 871struct proto raw_prot = {
843 .name = "RAW", 872 .name = "RAW",
844 .owner = THIS_MODULE, 873 .owner = THIS_MODULE,
@@ -861,6 +890,7 @@ struct proto raw_prot = {
861#ifdef CONFIG_COMPAT 890#ifdef CONFIG_COMPAT
862 .compat_setsockopt = compat_raw_setsockopt, 891 .compat_setsockopt = compat_raw_setsockopt,
863 .compat_getsockopt = compat_raw_getsockopt, 892 .compat_getsockopt = compat_raw_getsockopt,
893 .compat_ioctl = compat_raw_ioctl,
864#endif 894#endif
865}; 895};
866 896
@@ -949,7 +979,7 @@ static void raw_sock_seq_show(struct seq_file *seq, struct sock *sp, int i)
949 srcp = inet->inet_num; 979 srcp = inet->inet_num;
950 980
951 seq_printf(seq, "%4d: %08X:%04X %08X:%04X" 981 seq_printf(seq, "%4d: %08X:%04X %08X:%04X"
952 " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %d\n", 982 " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d\n",
953 i, src, srcp, dest, destp, sp->sk_state, 983 i, src, srcp, dest, destp, sp->sk_state,
954 sk_wmem_alloc_get(sp), 984 sk_wmem_alloc_get(sp),
955 sk_rmem_alloc_get(sp), 985 sk_rmem_alloc_get(sp),