diff options
Diffstat (limited to 'net/dccp')
-rw-r--r-- | net/dccp/dccp.h | 8 | ||||
-rw-r--r-- | net/dccp/ipv4.c | 79 | ||||
-rw-r--r-- | net/dccp/ipv6.c | 91 | ||||
-rw-r--r-- | net/dccp/minisocks.c | 2 | ||||
-rw-r--r-- | net/dccp/output.c | 6 | ||||
-rw-r--r-- | net/dccp/proto.c | 27 |
6 files changed, 114 insertions, 99 deletions
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index ba2ef94a230..f44d492d3b7 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h | |||
@@ -23,9 +23,9 @@ | |||
23 | * DCCP - specific warning and debugging macros. | 23 | * DCCP - specific warning and debugging macros. |
24 | */ | 24 | */ |
25 | #define DCCP_WARN(fmt, a...) LIMIT_NETDEBUG(KERN_WARNING "%s: " fmt, \ | 25 | #define DCCP_WARN(fmt, a...) LIMIT_NETDEBUG(KERN_WARNING "%s: " fmt, \ |
26 | __FUNCTION__, ##a) | 26 | __func__, ##a) |
27 | #define DCCP_CRIT(fmt, a...) printk(KERN_CRIT fmt " at %s:%d/%s()\n", ##a, \ | 27 | #define DCCP_CRIT(fmt, a...) printk(KERN_CRIT fmt " at %s:%d/%s()\n", ##a, \ |
28 | __FILE__, __LINE__, __FUNCTION__) | 28 | __FILE__, __LINE__, __func__) |
29 | #define DCCP_BUG(a...) do { DCCP_CRIT("BUG: " a); dump_stack(); } while(0) | 29 | #define DCCP_BUG(a...) do { DCCP_CRIT("BUG: " a); dump_stack(); } while(0) |
30 | #define DCCP_BUG_ON(cond) do { if (unlikely((cond) != 0)) \ | 30 | #define DCCP_BUG_ON(cond) do { if (unlikely((cond) != 0)) \ |
31 | DCCP_BUG("\"%s\" holds (exception!)", \ | 31 | DCCP_BUG("\"%s\" holds (exception!)", \ |
@@ -36,7 +36,7 @@ | |||
36 | printk(fmt, ##args); \ | 36 | printk(fmt, ##args); \ |
37 | } while(0) | 37 | } while(0) |
38 | #define DCCP_PR_DEBUG(enable, fmt, a...) DCCP_PRINTK(enable, KERN_DEBUG \ | 38 | #define DCCP_PR_DEBUG(enable, fmt, a...) DCCP_PRINTK(enable, KERN_DEBUG \ |
39 | "%s: " fmt, __FUNCTION__, ##a) | 39 | "%s: " fmt, __func__, ##a) |
40 | 40 | ||
41 | #ifdef CONFIG_IP_DCCP_DEBUG | 41 | #ifdef CONFIG_IP_DCCP_DEBUG |
42 | extern int dccp_debug; | 42 | extern int dccp_debug; |
@@ -296,7 +296,7 @@ extern unsigned int dccp_poll(struct file *file, struct socket *sock, | |||
296 | extern int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, | 296 | extern int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, |
297 | int addr_len); | 297 | int addr_len); |
298 | 298 | ||
299 | extern struct sk_buff *dccp_ctl_make_reset(struct socket *ctl, | 299 | extern struct sk_buff *dccp_ctl_make_reset(struct sock *sk, |
300 | struct sk_buff *skb); | 300 | struct sk_buff *skb); |
301 | extern int dccp_send_reset(struct sock *sk, enum dccp_reset_codes code); | 301 | extern int dccp_send_reset(struct sock *sk, enum dccp_reset_codes code); |
302 | extern void dccp_send_close(struct sock *sk, const int active); | 302 | extern void dccp_send_close(struct sock *sk, const int active); |
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index b3370441555..baa268d02e2 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 dccp_ctl_sk is the global socket data structure 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); |
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 490333d47c7..94e0c9495b2 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
@@ -33,8 +33,7 @@ | |||
33 | #include "ipv6.h" | 33 | #include "ipv6.h" |
34 | #include "feat.h" | 34 | #include "feat.h" |
35 | 35 | ||
36 | /* Socket used for sending RSTs and ACKs */ | 36 | /* dccp_v6_ctl_sk is used for sending RSTs and ACKs */ |
37 | static struct socket *dccp_v6_ctl_socket; | ||
38 | 37 | ||
39 | static struct inet_connection_sock_af_ops dccp_ipv6_mapped; | 38 | static struct inet_connection_sock_af_ops dccp_ipv6_mapped; |
40 | static struct inet_connection_sock_af_ops dccp_ipv6_af_ops; | 39 | static struct inet_connection_sock_af_ops dccp_ipv6_af_ops; |
@@ -95,7 +94,8 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
95 | int err; | 94 | int err; |
96 | __u64 seq; | 95 | __u64 seq; |
97 | 96 | ||
98 | sk = inet6_lookup(&init_net, &dccp_hashinfo, &hdr->daddr, dh->dccph_dport, | 97 | sk = inet6_lookup(dev_net(skb->dev), &dccp_hashinfo, |
98 | &hdr->daddr, dh->dccph_dport, | ||
99 | &hdr->saddr, dh->dccph_sport, inet6_iif(skb)); | 99 | &hdr->saddr, dh->dccph_sport, inet6_iif(skb)); |
100 | 100 | ||
101 | if (sk == NULL) { | 101 | if (sk == NULL) { |
@@ -224,8 +224,7 @@ out: | |||
224 | } | 224 | } |
225 | 225 | ||
226 | 226 | ||
227 | static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, | 227 | static int dccp_v6_send_response(struct sock *sk, struct request_sock *req) |
228 | struct dst_entry *dst) | ||
229 | { | 228 | { |
230 | struct inet6_request_sock *ireq6 = inet6_rsk(req); | 229 | struct inet6_request_sock *ireq6 = inet6_rsk(req); |
231 | struct ipv6_pinfo *np = inet6_sk(sk); | 230 | struct ipv6_pinfo *np = inet6_sk(sk); |
@@ -234,6 +233,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, | |||
234 | struct in6_addr *final_p = NULL, final; | 233 | struct in6_addr *final_p = NULL, final; |
235 | struct flowi fl; | 234 | struct flowi fl; |
236 | int err = -1; | 235 | int err = -1; |
236 | struct dst_entry *dst; | ||
237 | 237 | ||
238 | memset(&fl, 0, sizeof(fl)); | 238 | memset(&fl, 0, sizeof(fl)); |
239 | fl.proto = IPPROTO_DCCP; | 239 | fl.proto = IPPROTO_DCCP; |
@@ -245,28 +245,26 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, | |||
245 | fl.fl_ip_sport = inet_sk(sk)->sport; | 245 | fl.fl_ip_sport = inet_sk(sk)->sport; |
246 | security_req_classify_flow(req, &fl); | 246 | security_req_classify_flow(req, &fl); |
247 | 247 | ||
248 | if (dst == NULL) { | 248 | opt = np->opt; |
249 | opt = np->opt; | ||
250 | 249 | ||
251 | if (opt != NULL && opt->srcrt != NULL) { | 250 | if (opt != NULL && opt->srcrt != NULL) { |
252 | const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt; | 251 | const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt; |
253 | 252 | ||
254 | ipv6_addr_copy(&final, &fl.fl6_dst); | 253 | ipv6_addr_copy(&final, &fl.fl6_dst); |
255 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | 254 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); |
256 | final_p = &final; | 255 | final_p = &final; |
257 | } | 256 | } |
258 | 257 | ||
259 | err = ip6_dst_lookup(sk, &dst, &fl); | 258 | err = ip6_dst_lookup(sk, &dst, &fl); |
260 | if (err) | 259 | if (err) |
261 | goto done; | 260 | goto done; |
262 | 261 | ||
263 | if (final_p) | 262 | if (final_p) |
264 | ipv6_addr_copy(&fl.fl6_dst, final_p); | 263 | ipv6_addr_copy(&fl.fl6_dst, final_p); |
265 | 264 | ||
266 | err = xfrm_lookup(&dst, &fl, sk, 0); | 265 | err = xfrm_lookup(&dst, &fl, sk, 0); |
267 | if (err < 0) | 266 | if (err < 0) |
268 | goto done; | 267 | goto done; |
269 | } | ||
270 | 268 | ||
271 | skb = dccp_make_response(sk, dst, req); | 269 | skb = dccp_make_response(sk, dst, req); |
272 | if (skb != NULL) { | 270 | if (skb != NULL) { |
@@ -298,6 +296,8 @@ static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb) | |||
298 | struct ipv6hdr *rxip6h; | 296 | struct ipv6hdr *rxip6h; |
299 | struct sk_buff *skb; | 297 | struct sk_buff *skb; |
300 | struct flowi fl; | 298 | struct flowi fl; |
299 | struct net *net = dev_net(rxskb->dst->dev); | ||
300 | struct sock *ctl_sk = net->dccp.v6_ctl_sk; | ||
301 | 301 | ||
302 | if (dccp_hdr(rxskb)->dccph_type == DCCP_PKT_RESET) | 302 | if (dccp_hdr(rxskb)->dccph_type == DCCP_PKT_RESET) |
303 | return; | 303 | return; |
@@ -305,7 +305,7 @@ static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb) | |||
305 | if (!ipv6_unicast_destination(rxskb)) | 305 | if (!ipv6_unicast_destination(rxskb)) |
306 | return; | 306 | return; |
307 | 307 | ||
308 | skb = dccp_ctl_make_reset(dccp_v6_ctl_socket, rxskb); | 308 | skb = dccp_ctl_make_reset(ctl_sk, rxskb); |
309 | if (skb == NULL) | 309 | if (skb == NULL) |
310 | return; | 310 | return; |
311 | 311 | ||
@@ -324,9 +324,9 @@ static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb) | |||
324 | security_skb_classify_flow(rxskb, &fl); | 324 | security_skb_classify_flow(rxskb, &fl); |
325 | 325 | ||
326 | /* sk = NULL, but it is safe for now. RST socket required. */ | 326 | /* sk = NULL, but it is safe for now. RST socket required. */ |
327 | if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) { | 327 | if (!ip6_dst_lookup(ctl_sk, &skb->dst, &fl)) { |
328 | if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) { | 328 | if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) { |
329 | ip6_xmit(dccp_v6_ctl_socket->sk, skb, &fl, NULL, 0); | 329 | ip6_xmit(ctl_sk, skb, &fl, NULL, 0); |
330 | DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); | 330 | DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); |
331 | DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS); | 331 | DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS); |
332 | return; | 332 | return; |
@@ -360,7 +360,7 @@ static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) | |||
360 | if (req != NULL) | 360 | if (req != NULL) |
361 | return dccp_check_req(sk, skb, req, prev); | 361 | return dccp_check_req(sk, skb, req, prev); |
362 | 362 | ||
363 | nsk = __inet6_lookup_established(&init_net, &dccp_hashinfo, | 363 | nsk = __inet6_lookup_established(sock_net(sk), &dccp_hashinfo, |
364 | &iph->saddr, dh->dccph_sport, | 364 | &iph->saddr, dh->dccph_sport, |
365 | &iph->daddr, ntohs(dh->dccph_dport), | 365 | &iph->daddr, ntohs(dh->dccph_dport), |
366 | inet6_iif(skb)); | 366 | inet6_iif(skb)); |
@@ -448,7 +448,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
448 | dreq->dreq_iss = dccp_v6_init_sequence(skb); | 448 | dreq->dreq_iss = dccp_v6_init_sequence(skb); |
449 | dreq->dreq_service = service; | 449 | dreq->dreq_service = service; |
450 | 450 | ||
451 | if (dccp_v6_send_response(sk, req, NULL)) | 451 | if (dccp_v6_send_response(sk, req)) |
452 | goto drop_and_free; | 452 | goto drop_and_free; |
453 | 453 | ||
454 | inet6_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT); | 454 | inet6_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT); |
@@ -791,8 +791,8 @@ static int dccp_v6_rcv(struct sk_buff *skb) | |||
791 | 791 | ||
792 | /* Step 2: | 792 | /* Step 2: |
793 | * Look up flow ID in table and get corresponding socket */ | 793 | * Look up flow ID in table and get corresponding socket */ |
794 | sk = __inet6_lookup(&init_net, &dccp_hashinfo, &ipv6_hdr(skb)->saddr, | 794 | sk = __inet6_lookup(dev_net(skb->dst->dev), &dccp_hashinfo, |
795 | dh->dccph_sport, | 795 | &ipv6_hdr(skb)->saddr, dh->dccph_sport, |
796 | &ipv6_hdr(skb)->daddr, ntohs(dh->dccph_dport), | 796 | &ipv6_hdr(skb)->daddr, ntohs(dh->dccph_dport), |
797 | inet6_iif(skb)); | 797 | inet6_iif(skb)); |
798 | /* | 798 | /* |
@@ -1102,8 +1102,6 @@ static struct timewait_sock_ops dccp6_timewait_sock_ops = { | |||
1102 | .twsk_obj_size = sizeof(struct dccp6_timewait_sock), | 1102 | .twsk_obj_size = sizeof(struct dccp6_timewait_sock), |
1103 | }; | 1103 | }; |
1104 | 1104 | ||
1105 | DEFINE_PROTO_INUSE(dccp_v6) | ||
1106 | |||
1107 | static struct proto dccp_v6_prot = { | 1105 | static struct proto dccp_v6_prot = { |
1108 | .name = "DCCPv6", | 1106 | .name = "DCCPv6", |
1109 | .owner = THIS_MODULE, | 1107 | .owner = THIS_MODULE, |
@@ -1128,12 +1126,11 @@ static struct proto dccp_v6_prot = { | |||
1128 | .obj_size = sizeof(struct dccp6_sock), | 1126 | .obj_size = sizeof(struct dccp6_sock), |
1129 | .rsk_prot = &dccp6_request_sock_ops, | 1127 | .rsk_prot = &dccp6_request_sock_ops, |
1130 | .twsk_prot = &dccp6_timewait_sock_ops, | 1128 | .twsk_prot = &dccp6_timewait_sock_ops, |
1131 | .hashinfo = &dccp_hashinfo, | 1129 | .h.hashinfo = &dccp_hashinfo, |
1132 | #ifdef CONFIG_COMPAT | 1130 | #ifdef CONFIG_COMPAT |
1133 | .compat_setsockopt = compat_dccp_setsockopt, | 1131 | .compat_setsockopt = compat_dccp_setsockopt, |
1134 | .compat_getsockopt = compat_dccp_getsockopt, | 1132 | .compat_getsockopt = compat_dccp_getsockopt, |
1135 | #endif | 1133 | #endif |
1136 | REF_PROTO_INUSE(dccp_v6) | ||
1137 | }; | 1134 | }; |
1138 | 1135 | ||
1139 | static struct inet6_protocol dccp_v6_protocol = { | 1136 | static struct inet6_protocol dccp_v6_protocol = { |
@@ -1176,6 +1173,25 @@ static struct inet_protosw dccp_v6_protosw = { | |||
1176 | .flags = INET_PROTOSW_ICSK, | 1173 | .flags = INET_PROTOSW_ICSK, |
1177 | }; | 1174 | }; |
1178 | 1175 | ||
1176 | static int dccp_v6_init_net(struct net *net) | ||
1177 | { | ||
1178 | int err; | ||
1179 | |||
1180 | err = inet_ctl_sock_create(&net->dccp.v6_ctl_sk, PF_INET6, | ||
1181 | SOCK_DCCP, IPPROTO_DCCP, net); | ||
1182 | return err; | ||
1183 | } | ||
1184 | |||
1185 | static void dccp_v6_exit_net(struct net *net) | ||
1186 | { | ||
1187 | inet_ctl_sock_destroy(net->dccp.v6_ctl_sk); | ||
1188 | } | ||
1189 | |||
1190 | static struct pernet_operations dccp_v6_ops = { | ||
1191 | .init = dccp_v6_init_net, | ||
1192 | .exit = dccp_v6_exit_net, | ||
1193 | }; | ||
1194 | |||
1179 | static int __init dccp_v6_init(void) | 1195 | static int __init dccp_v6_init(void) |
1180 | { | 1196 | { |
1181 | int err = proto_register(&dccp_v6_prot, 1); | 1197 | int err = proto_register(&dccp_v6_prot, 1); |
@@ -1189,13 +1205,13 @@ static int __init dccp_v6_init(void) | |||
1189 | 1205 | ||
1190 | inet6_register_protosw(&dccp_v6_protosw); | 1206 | inet6_register_protosw(&dccp_v6_protosw); |
1191 | 1207 | ||
1192 | err = inet_csk_ctl_sock_create(&dccp_v6_ctl_socket, PF_INET6, | 1208 | err = register_pernet_subsys(&dccp_v6_ops); |
1193 | SOCK_DCCP, IPPROTO_DCCP); | ||
1194 | if (err != 0) | 1209 | if (err != 0) |
1195 | goto out_unregister_protosw; | 1210 | goto out_destroy_ctl_sock; |
1196 | out: | 1211 | out: |
1197 | return err; | 1212 | return err; |
1198 | out_unregister_protosw: | 1213 | |
1214 | out_destroy_ctl_sock: | ||
1199 | inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP); | 1215 | inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP); |
1200 | inet6_unregister_protosw(&dccp_v6_protosw); | 1216 | inet6_unregister_protosw(&dccp_v6_protosw); |
1201 | out_unregister_proto: | 1217 | out_unregister_proto: |
@@ -1205,6 +1221,7 @@ out_unregister_proto: | |||
1205 | 1221 | ||
1206 | static void __exit dccp_v6_exit(void) | 1222 | static void __exit dccp_v6_exit(void) |
1207 | { | 1223 | { |
1224 | unregister_pernet_subsys(&dccp_v6_ops); | ||
1208 | inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP); | 1225 | inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP); |
1209 | inet6_unregister_protosw(&dccp_v6_protosw); | 1226 | inet6_unregister_protosw(&dccp_v6_protosw); |
1210 | proto_unregister(&dccp_v6_prot); | 1227 | proto_unregister(&dccp_v6_prot); |
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 027d1814e1a..33ad48321b0 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c | |||
@@ -216,7 +216,7 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb, | |||
216 | * counter (backoff, monitored by dccp_response_timer). | 216 | * counter (backoff, monitored by dccp_response_timer). |
217 | */ | 217 | */ |
218 | req->retrans++; | 218 | req->retrans++; |
219 | req->rsk_ops->rtx_syn_ack(sk, req, NULL); | 219 | req->rsk_ops->rtx_syn_ack(sk, req); |
220 | } | 220 | } |
221 | /* Network Duplicate, discard packet */ | 221 | /* Network Duplicate, discard packet */ |
222 | return NULL; | 222 | return NULL; |
diff --git a/net/dccp/output.c b/net/dccp/output.c index 3d7d628d870..1f8a9b64c08 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c | |||
@@ -347,7 +347,7 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, | |||
347 | EXPORT_SYMBOL_GPL(dccp_make_response); | 347 | EXPORT_SYMBOL_GPL(dccp_make_response); |
348 | 348 | ||
349 | /* answer offending packet in @rcv_skb with Reset from control socket @ctl */ | 349 | /* answer offending packet in @rcv_skb with Reset from control socket @ctl */ |
350 | struct sk_buff *dccp_ctl_make_reset(struct socket *ctl, struct sk_buff *rcv_skb) | 350 | struct sk_buff *dccp_ctl_make_reset(struct sock *sk, struct sk_buff *rcv_skb) |
351 | { | 351 | { |
352 | struct dccp_hdr *rxdh = dccp_hdr(rcv_skb), *dh; | 352 | struct dccp_hdr *rxdh = dccp_hdr(rcv_skb), *dh; |
353 | struct dccp_skb_cb *dcb = DCCP_SKB_CB(rcv_skb); | 353 | struct dccp_skb_cb *dcb = DCCP_SKB_CB(rcv_skb); |
@@ -357,11 +357,11 @@ struct sk_buff *dccp_ctl_make_reset(struct socket *ctl, struct sk_buff *rcv_skb) | |||
357 | struct dccp_hdr_reset *dhr; | 357 | struct dccp_hdr_reset *dhr; |
358 | struct sk_buff *skb; | 358 | struct sk_buff *skb; |
359 | 359 | ||
360 | skb = alloc_skb(ctl->sk->sk_prot->max_header, GFP_ATOMIC); | 360 | skb = alloc_skb(sk->sk_prot->max_header, GFP_ATOMIC); |
361 | if (skb == NULL) | 361 | if (skb == NULL) |
362 | return NULL; | 362 | return NULL; |
363 | 363 | ||
364 | skb_reserve(skb, ctl->sk->sk_prot->max_header); | 364 | skb_reserve(skb, sk->sk_prot->max_header); |
365 | 365 | ||
366 | /* Swap the send and the receive. */ | 366 | /* Swap the send and the receive. */ |
367 | dh = dccp_zeroed_hdr(skb, dccp_hdr_reset_len); | 367 | dh = dccp_zeroed_hdr(skb, dccp_hdr_reset_len); |
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index c91d3c1fd30..a4c1b36f4bc 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c | |||
@@ -1010,33 +1010,14 @@ void dccp_shutdown(struct sock *sk, int how) | |||
1010 | 1010 | ||
1011 | EXPORT_SYMBOL_GPL(dccp_shutdown); | 1011 | EXPORT_SYMBOL_GPL(dccp_shutdown); |
1012 | 1012 | ||
1013 | static int __init dccp_mib_init(void) | 1013 | static inline int dccp_mib_init(void) |
1014 | { | 1014 | { |
1015 | int rc = -ENOMEM; | 1015 | return snmp_mib_init((void**)dccp_statistics, sizeof(struct dccp_mib)); |
1016 | |||
1017 | dccp_statistics[0] = alloc_percpu(struct dccp_mib); | ||
1018 | if (dccp_statistics[0] == NULL) | ||
1019 | goto out; | ||
1020 | |||
1021 | dccp_statistics[1] = alloc_percpu(struct dccp_mib); | ||
1022 | if (dccp_statistics[1] == NULL) | ||
1023 | goto out_free_one; | ||
1024 | |||
1025 | rc = 0; | ||
1026 | out: | ||
1027 | return rc; | ||
1028 | out_free_one: | ||
1029 | free_percpu(dccp_statistics[0]); | ||
1030 | dccp_statistics[0] = NULL; | ||
1031 | goto out; | ||
1032 | |||
1033 | } | 1016 | } |
1034 | 1017 | ||
1035 | static void dccp_mib_exit(void) | 1018 | static inline void dccp_mib_exit(void) |
1036 | { | 1019 | { |
1037 | free_percpu(dccp_statistics[0]); | 1020 | snmp_mib_free((void**)dccp_statistics); |
1038 | free_percpu(dccp_statistics[1]); | ||
1039 | dccp_statistics[0] = dccp_statistics[1] = NULL; | ||
1040 | } | 1021 | } |
1041 | 1022 | ||
1042 | static int thash_entries; | 1023 | static int thash_entries; |