diff options
Diffstat (limited to 'net/dccp/ipv4.c')
-rw-r--r-- | net/dccp/ipv4.c | 79 |
1 files changed, 48 insertions, 31 deletions
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index b33704415555..b348dd70c685 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c | |||
@@ -32,11 +32,10 @@ | |||
32 | #include "feat.h" | 32 | #include "feat.h" |
33 | 33 | ||
34 | /* | 34 | /* |
35 | * This is the global socket data structure used for responding to | 35 | * The per-net dccp.v4_ctl_sk socket is used for responding to |
36 | * the Out-of-the-blue (OOTB) packets. A control sock will be created | 36 | * the Out-of-the-blue (OOTB) packets. A control sock will be created |
37 | * for this socket at the initialization time. | 37 | * for this socket at the initialization time. |
38 | */ | 38 | */ |
39 | static struct socket *dccp_v4_ctl_socket; | ||
40 | 39 | ||
41 | int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | 40 | int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) |
42 | { | 41 | { |
@@ -212,8 +211,9 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) | |||
212 | return; | 211 | return; |
213 | } | 212 | } |
214 | 213 | ||
215 | sk = inet_lookup(&init_net, &dccp_hashinfo, iph->daddr, dh->dccph_dport, | 214 | sk = inet_lookup(dev_net(skb->dev), &dccp_hashinfo, |
216 | iph->saddr, dh->dccph_sport, inet_iif(skb)); | 215 | iph->daddr, dh->dccph_dport, |
216 | iph->saddr, dh->dccph_sport, inet_iif(skb)); | ||
217 | if (sk == NULL) { | 217 | if (sk == NULL) { |
218 | ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); | 218 | ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); |
219 | return; | 219 | return; |
@@ -430,7 +430,7 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) | |||
430 | if (req != NULL) | 430 | if (req != NULL) |
431 | return dccp_check_req(sk, skb, req, prev); | 431 | return dccp_check_req(sk, skb, req, prev); |
432 | 432 | ||
433 | nsk = inet_lookup_established(&init_net, &dccp_hashinfo, | 433 | nsk = inet_lookup_established(sock_net(sk), &dccp_hashinfo, |
434 | iph->saddr, dh->dccph_sport, | 434 | iph->saddr, dh->dccph_sport, |
435 | iph->daddr, dh->dccph_dport, | 435 | iph->daddr, dh->dccph_dport, |
436 | inet_iif(skb)); | 436 | inet_iif(skb)); |
@@ -446,11 +446,11 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) | |||
446 | return sk; | 446 | return sk; |
447 | } | 447 | } |
448 | 448 | ||
449 | static struct dst_entry* dccp_v4_route_skb(struct sock *sk, | 449 | static struct dst_entry* dccp_v4_route_skb(struct net *net, struct sock *sk, |
450 | struct sk_buff *skb) | 450 | struct sk_buff *skb) |
451 | { | 451 | { |
452 | struct rtable *rt; | 452 | struct rtable *rt; |
453 | struct flowi fl = { .oif = ((struct rtable *)skb->dst)->rt_iif, | 453 | struct flowi fl = { .oif = skb->rtable->rt_iif, |
454 | .nl_u = { .ip4_u = | 454 | .nl_u = { .ip4_u = |
455 | { .daddr = ip_hdr(skb)->saddr, | 455 | { .daddr = ip_hdr(skb)->saddr, |
456 | .saddr = ip_hdr(skb)->daddr, | 456 | .saddr = ip_hdr(skb)->daddr, |
@@ -463,7 +463,7 @@ static struct dst_entry* dccp_v4_route_skb(struct sock *sk, | |||
463 | }; | 463 | }; |
464 | 464 | ||
465 | security_skb_classify_flow(skb, &fl); | 465 | security_skb_classify_flow(skb, &fl); |
466 | if (ip_route_output_flow(&init_net, &rt, &fl, sk, 0)) { | 466 | if (ip_route_output_flow(net, &rt, &fl, sk, 0)) { |
467 | IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); | 467 | IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); |
468 | return NULL; | 468 | return NULL; |
469 | } | 469 | } |
@@ -471,15 +471,14 @@ static struct dst_entry* dccp_v4_route_skb(struct sock *sk, | |||
471 | return &rt->u.dst; | 471 | return &rt->u.dst; |
472 | } | 472 | } |
473 | 473 | ||
474 | static int dccp_v4_send_response(struct sock *sk, struct request_sock *req, | 474 | static int dccp_v4_send_response(struct sock *sk, struct request_sock *req) |
475 | struct dst_entry *dst) | ||
476 | { | 475 | { |
477 | int err = -1; | 476 | int err = -1; |
478 | struct sk_buff *skb; | 477 | struct sk_buff *skb; |
478 | struct dst_entry *dst; | ||
479 | 479 | ||
480 | /* First, grab a route. */ | 480 | dst = inet_csk_route_req(sk, req); |
481 | 481 | if (dst == NULL) | |
482 | if (dst == NULL && (dst = inet_csk_route_req(sk, req)) == NULL) | ||
483 | goto out; | 482 | goto out; |
484 | 483 | ||
485 | skb = dccp_make_response(sk, dst, req); | 484 | skb = dccp_make_response(sk, dst, req); |
@@ -506,19 +505,21 @@ static void dccp_v4_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb) | |||
506 | const struct iphdr *rxiph; | 505 | const struct iphdr *rxiph; |
507 | struct sk_buff *skb; | 506 | struct sk_buff *skb; |
508 | struct dst_entry *dst; | 507 | struct dst_entry *dst; |
508 | struct net *net = dev_net(rxskb->dst->dev); | ||
509 | struct sock *ctl_sk = net->dccp.v4_ctl_sk; | ||
509 | 510 | ||
510 | /* Never send a reset in response to a reset. */ | 511 | /* Never send a reset in response to a reset. */ |
511 | if (dccp_hdr(rxskb)->dccph_type == DCCP_PKT_RESET) | 512 | if (dccp_hdr(rxskb)->dccph_type == DCCP_PKT_RESET) |
512 | return; | 513 | return; |
513 | 514 | ||
514 | if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL) | 515 | if (rxskb->rtable->rt_type != RTN_LOCAL) |
515 | return; | 516 | return; |
516 | 517 | ||
517 | dst = dccp_v4_route_skb(dccp_v4_ctl_socket->sk, rxskb); | 518 | dst = dccp_v4_route_skb(net, ctl_sk, rxskb); |
518 | if (dst == NULL) | 519 | if (dst == NULL) |
519 | return; | 520 | return; |
520 | 521 | ||
521 | skb = dccp_ctl_make_reset(dccp_v4_ctl_socket, rxskb); | 522 | skb = dccp_ctl_make_reset(ctl_sk, rxskb); |
522 | if (skb == NULL) | 523 | if (skb == NULL) |
523 | goto out; | 524 | goto out; |
524 | 525 | ||
@@ -527,10 +528,10 @@ static void dccp_v4_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb) | |||
527 | rxiph->daddr); | 528 | rxiph->daddr); |
528 | skb->dst = dst_clone(dst); | 529 | skb->dst = dst_clone(dst); |
529 | 530 | ||
530 | bh_lock_sock(dccp_v4_ctl_socket->sk); | 531 | bh_lock_sock(ctl_sk); |
531 | err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk, | 532 | err = ip_build_and_send_pkt(skb, ctl_sk, |
532 | rxiph->daddr, rxiph->saddr, NULL); | 533 | rxiph->daddr, rxiph->saddr, NULL); |
533 | bh_unlock_sock(dccp_v4_ctl_socket->sk); | 534 | bh_unlock_sock(ctl_sk); |
534 | 535 | ||
535 | if (net_xmit_eval(err) == 0) { | 536 | if (net_xmit_eval(err) == 0) { |
536 | DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); | 537 | DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); |
@@ -563,8 +564,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
563 | struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); | 564 | struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); |
564 | 565 | ||
565 | /* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */ | 566 | /* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */ |
566 | if (((struct rtable *)skb->dst)->rt_flags & | 567 | if (skb->rtable->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) |
567 | (RTCF_BROADCAST | RTCF_MULTICAST)) | ||
568 | return 0; /* discard, don't send a reset here */ | 568 | return 0; /* discard, don't send a reset here */ |
569 | 569 | ||
570 | if (dccp_bad_service_code(sk, service)) { | 570 | if (dccp_bad_service_code(sk, service)) { |
@@ -619,7 +619,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
619 | dreq->dreq_iss = dccp_v4_init_sequence(skb); | 619 | dreq->dreq_iss = dccp_v4_init_sequence(skb); |
620 | dreq->dreq_service = service; | 620 | dreq->dreq_service = service; |
621 | 621 | ||
622 | if (dccp_v4_send_response(sk, req, NULL)) | 622 | if (dccp_v4_send_response(sk, req)) |
623 | goto drop_and_free; | 623 | goto drop_and_free; |
624 | 624 | ||
625 | inet_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT); | 625 | inet_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT); |
@@ -810,7 +810,7 @@ static int dccp_v4_rcv(struct sk_buff *skb) | |||
810 | 810 | ||
811 | /* Step 2: | 811 | /* Step 2: |
812 | * Look up flow ID in table and get corresponding socket */ | 812 | * Look up flow ID in table and get corresponding socket */ |
813 | sk = __inet_lookup(&init_net, &dccp_hashinfo, | 813 | sk = __inet_lookup(dev_net(skb->dst->dev), &dccp_hashinfo, |
814 | iph->saddr, dh->dccph_sport, | 814 | iph->saddr, dh->dccph_sport, |
815 | iph->daddr, dh->dccph_dport, inet_iif(skb)); | 815 | iph->daddr, dh->dccph_dport, inet_iif(skb)); |
816 | /* | 816 | /* |
@@ -916,8 +916,6 @@ static struct timewait_sock_ops dccp_timewait_sock_ops = { | |||
916 | .twsk_obj_size = sizeof(struct inet_timewait_sock), | 916 | .twsk_obj_size = sizeof(struct inet_timewait_sock), |
917 | }; | 917 | }; |
918 | 918 | ||
919 | DEFINE_PROTO_INUSE(dccp_v4) | ||
920 | |||
921 | static struct proto dccp_v4_prot = { | 919 | static struct proto dccp_v4_prot = { |
922 | .name = "DCCP", | 920 | .name = "DCCP", |
923 | .owner = THIS_MODULE, | 921 | .owner = THIS_MODULE, |
@@ -942,18 +940,18 @@ static struct proto dccp_v4_prot = { | |||
942 | .obj_size = sizeof(struct dccp_sock), | 940 | .obj_size = sizeof(struct dccp_sock), |
943 | .rsk_prot = &dccp_request_sock_ops, | 941 | .rsk_prot = &dccp_request_sock_ops, |
944 | .twsk_prot = &dccp_timewait_sock_ops, | 942 | .twsk_prot = &dccp_timewait_sock_ops, |
945 | .hashinfo = &dccp_hashinfo, | 943 | .h.hashinfo = &dccp_hashinfo, |
946 | #ifdef CONFIG_COMPAT | 944 | #ifdef CONFIG_COMPAT |
947 | .compat_setsockopt = compat_dccp_setsockopt, | 945 | .compat_setsockopt = compat_dccp_setsockopt, |
948 | .compat_getsockopt = compat_dccp_getsockopt, | 946 | .compat_getsockopt = compat_dccp_getsockopt, |
949 | #endif | 947 | #endif |
950 | REF_PROTO_INUSE(dccp_v4) | ||
951 | }; | 948 | }; |
952 | 949 | ||
953 | static struct net_protocol dccp_v4_protocol = { | 950 | static struct net_protocol dccp_v4_protocol = { |
954 | .handler = dccp_v4_rcv, | 951 | .handler = dccp_v4_rcv, |
955 | .err_handler = dccp_v4_err, | 952 | .err_handler = dccp_v4_err, |
956 | .no_policy = 1, | 953 | .no_policy = 1, |
954 | .netns_ok = 1, | ||
957 | }; | 955 | }; |
958 | 956 | ||
959 | static const struct proto_ops inet_dccp_ops = { | 957 | static const struct proto_ops inet_dccp_ops = { |
@@ -993,6 +991,25 @@ static struct inet_protosw dccp_v4_protosw = { | |||
993 | .flags = INET_PROTOSW_ICSK, | 991 | .flags = INET_PROTOSW_ICSK, |
994 | }; | 992 | }; |
995 | 993 | ||
994 | static int dccp_v4_init_net(struct net *net) | ||
995 | { | ||
996 | int err; | ||
997 | |||
998 | err = inet_ctl_sock_create(&net->dccp.v4_ctl_sk, PF_INET, | ||
999 | SOCK_DCCP, IPPROTO_DCCP, net); | ||
1000 | return err; | ||
1001 | } | ||
1002 | |||
1003 | static void dccp_v4_exit_net(struct net *net) | ||
1004 | { | ||
1005 | inet_ctl_sock_destroy(net->dccp.v4_ctl_sk); | ||
1006 | } | ||
1007 | |||
1008 | static struct pernet_operations dccp_v4_ops = { | ||
1009 | .init = dccp_v4_init_net, | ||
1010 | .exit = dccp_v4_exit_net, | ||
1011 | }; | ||
1012 | |||
996 | static int __init dccp_v4_init(void) | 1013 | static int __init dccp_v4_init(void) |
997 | { | 1014 | { |
998 | int err = proto_register(&dccp_v4_prot, 1); | 1015 | int err = proto_register(&dccp_v4_prot, 1); |
@@ -1006,13 +1023,12 @@ static int __init dccp_v4_init(void) | |||
1006 | 1023 | ||
1007 | inet_register_protosw(&dccp_v4_protosw); | 1024 | inet_register_protosw(&dccp_v4_protosw); |
1008 | 1025 | ||
1009 | err = inet_csk_ctl_sock_create(&dccp_v4_ctl_socket, PF_INET, | 1026 | err = register_pernet_subsys(&dccp_v4_ops); |
1010 | SOCK_DCCP, IPPROTO_DCCP); | ||
1011 | if (err) | 1027 | if (err) |
1012 | goto out_unregister_protosw; | 1028 | goto out_destroy_ctl_sock; |
1013 | out: | 1029 | out: |
1014 | return err; | 1030 | return err; |
1015 | out_unregister_protosw: | 1031 | out_destroy_ctl_sock: |
1016 | inet_unregister_protosw(&dccp_v4_protosw); | 1032 | inet_unregister_protosw(&dccp_v4_protosw); |
1017 | inet_del_protocol(&dccp_v4_protocol, IPPROTO_DCCP); | 1033 | inet_del_protocol(&dccp_v4_protocol, IPPROTO_DCCP); |
1018 | out_proto_unregister: | 1034 | out_proto_unregister: |
@@ -1022,6 +1038,7 @@ out_proto_unregister: | |||
1022 | 1038 | ||
1023 | static void __exit dccp_v4_exit(void) | 1039 | static void __exit dccp_v4_exit(void) |
1024 | { | 1040 | { |
1041 | unregister_pernet_subsys(&dccp_v4_ops); | ||
1025 | inet_unregister_protosw(&dccp_v4_protosw); | 1042 | inet_unregister_protosw(&dccp_v4_protosw); |
1026 | inet_del_protocol(&dccp_v4_protocol, IPPROTO_DCCP); | 1043 | inet_del_protocol(&dccp_v4_protocol, IPPROTO_DCCP); |
1027 | proto_unregister(&dccp_v4_prot); | 1044 | proto_unregister(&dccp_v4_prot); |