X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=net%2Fdccp%2Fipv4.c;h=2622ace17c467d528efbc41de9705a5b4d4ec49e;hb=8ffa5b65968262ba6bb046329972791c0d960745;hp=4ca8b0c93c80781ea6ce7b181b8ce05afbdb52fb;hpb=8e8e43843ba3ced0c657cbc0fdb10644ec60f772;p=linux-2.6 diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 4ca8b0c93c..2622ace17c 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -32,11 +32,10 @@ #include "feat.h" /* - * This is the global socket data structure used for responding to + * The per-net dccp.v4_ctl_sk socket is used for responding to * the Out-of-the-blue (OOTB) packets. A control sock will be created * for this socket at the initialization time. */ -static struct socket *dccp_v4_ctl_socket; int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) { @@ -206,16 +205,18 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) struct sock *sk; __u64 seq; int err; + struct net *net = dev_net(skb->dev); if (skb->len < (iph->ihl << 2) + 8) { - ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); + ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); return; } - sk = inet_lookup(&init_net, &dccp_hashinfo, iph->daddr, dh->dccph_dport, - iph->saddr, dh->dccph_sport, inet_iif(skb)); + sk = inet_lookup(net, &dccp_hashinfo, + iph->daddr, dh->dccph_dport, + iph->saddr, dh->dccph_sport, inet_iif(skb)); if (sk == NULL) { - ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); + ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); return; } @@ -229,7 +230,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) * servers this needs to be solved differently. */ if (sock_owned_by_user(sk)) - NET_INC_STATS_BH(LINUX_MIB_LOCKDROPPEDICMPS); + NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS); if (sk->sk_state == DCCP_CLOSED) goto out; @@ -238,7 +239,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) seq = dccp_hdr_seq(dh); if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) && !between48(seq, dp->dccps_swl, dp->dccps_swh)) { - NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS); + NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS); goto out; } @@ -285,7 +286,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) BUG_TRAP(!req->sk); if (seq != dccp_rsk(req)->dreq_iss) { - NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS); + NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS); goto out; } /* @@ -408,9 +409,9 @@ struct sock *dccp_v4_request_recv_sock(struct sock *sk, struct sk_buff *skb, return newsk; exit_overflow: - NET_INC_STATS_BH(LINUX_MIB_LISTENOVERFLOWS); + NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); exit: - NET_INC_STATS_BH(LINUX_MIB_LISTENDROPS); + NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); dst_release(dst); return NULL; } @@ -430,7 +431,7 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) if (req != NULL) return dccp_check_req(sk, skb, req, prev); - nsk = inet_lookup_established(&init_net, &dccp_hashinfo, + nsk = inet_lookup_established(sock_net(sk), &dccp_hashinfo, iph->saddr, dh->dccph_sport, iph->daddr, dh->dccph_dport, inet_iif(skb)); @@ -446,7 +447,7 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) return sk; } -static struct dst_entry* dccp_v4_route_skb(struct sock *sk, +static struct dst_entry* dccp_v4_route_skb(struct net *net, struct sock *sk, struct sk_buff *skb) { struct rtable *rt; @@ -463,8 +464,8 @@ static struct dst_entry* dccp_v4_route_skb(struct sock *sk, }; security_skb_classify_flow(skb, &fl); - if (ip_route_output_flow(&init_net, &rt, &fl, sk, 0)) { - IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); + if (ip_route_output_flow(net, &rt, &fl, sk, 0)) { + IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); return NULL; } @@ -488,7 +489,6 @@ static int dccp_v4_send_response(struct sock *sk, struct request_sock *req) dh->dccph_checksum = dccp_v4_csum_finish(skb, ireq->loc_addr, ireq->rmt_addr); - memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr, ireq->rmt_addr, ireq->opt); @@ -506,6 +506,8 @@ static void dccp_v4_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb) const struct iphdr *rxiph; struct sk_buff *skb; struct dst_entry *dst; + struct net *net = dev_net(rxskb->dst->dev); + struct sock *ctl_sk = net->dccp.v4_ctl_sk; /* Never send a reset in response to a reset. */ if (dccp_hdr(rxskb)->dccph_type == DCCP_PKT_RESET) @@ -514,11 +516,11 @@ static void dccp_v4_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb) if (rxskb->rtable->rt_type != RTN_LOCAL) return; - dst = dccp_v4_route_skb(dccp_v4_ctl_socket->sk, rxskb); + dst = dccp_v4_route_skb(net, ctl_sk, rxskb); if (dst == NULL) return; - skb = dccp_ctl_make_reset(dccp_v4_ctl_socket, rxskb); + skb = dccp_ctl_make_reset(ctl_sk, rxskb); if (skb == NULL) goto out; @@ -527,10 +529,10 @@ static void dccp_v4_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb) rxiph->daddr); skb->dst = dst_clone(dst); - bh_lock_sock(dccp_v4_ctl_socket->sk); - err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk, + bh_lock_sock(ctl_sk); + err = ip_build_and_send_pkt(skb, ctl_sk, rxiph->daddr, rxiph->saddr, NULL); - bh_unlock_sock(dccp_v4_ctl_socket->sk); + bh_unlock_sock(ctl_sk); if (net_xmit_eval(err) == 0) { DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); @@ -588,7 +590,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) goto drop; - req = reqsk_alloc(&dccp_request_sock_ops); + req = inet_reqsk_alloc(&dccp_request_sock_ops); if (req == NULL) goto drop; @@ -604,7 +606,6 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) ireq = inet_rsk(req); ireq->loc_addr = ip_hdr(skb)->daddr; ireq->rmt_addr = ip_hdr(skb)->saddr; - ireq->opt = NULL; /* * Step 3: Process LISTEN state @@ -738,8 +739,8 @@ int dccp_invalid_packet(struct sk_buff *skb) * If P.type is not Data, Ack, or DataAck and P.X == 0 (the packet * has short sequence numbers), drop packet and return */ - if (dh->dccph_type >= DCCP_PKT_DATA && - dh->dccph_type <= DCCP_PKT_DATAACK && dh->dccph_x == 0) { + if ((dh->dccph_type < DCCP_PKT_DATA || + dh->dccph_type > DCCP_PKT_DATAACK) && dh->dccph_x == 0) { DCCP_WARN("P.type (%s) not Data || [Data]Ack, while P.X == 0\n", dccp_packet_name(dh->dccph_type)); return 1; @@ -809,7 +810,7 @@ static int dccp_v4_rcv(struct sk_buff *skb) /* Step 2: * Look up flow ID in table and get corresponding socket */ - sk = __inet_lookup(&init_net, &dccp_hashinfo, + sk = __inet_lookup(dev_net(skb->dst->dev), &dccp_hashinfo, iph->saddr, dh->dccph_sport, iph->daddr, dh->dccph_dport, inet_iif(skb)); /* @@ -915,8 +916,6 @@ static struct timewait_sock_ops dccp_timewait_sock_ops = { .twsk_obj_size = sizeof(struct inet_timewait_sock), }; -DEFINE_PROTO_INUSE(dccp_v4) - static struct proto dccp_v4_prot = { .name = "DCCP", .owner = THIS_MODULE, @@ -946,13 +945,13 @@ static struct proto dccp_v4_prot = { .compat_setsockopt = compat_dccp_setsockopt, .compat_getsockopt = compat_dccp_getsockopt, #endif - REF_PROTO_INUSE(dccp_v4) }; static struct net_protocol dccp_v4_protocol = { .handler = dccp_v4_rcv, .err_handler = dccp_v4_err, .no_policy = 1, + .netns_ok = 1, }; static const struct proto_ops inet_dccp_ops = { @@ -992,6 +991,25 @@ static struct inet_protosw dccp_v4_protosw = { .flags = INET_PROTOSW_ICSK, }; +static int dccp_v4_init_net(struct net *net) +{ + int err; + + err = inet_ctl_sock_create(&net->dccp.v4_ctl_sk, PF_INET, + SOCK_DCCP, IPPROTO_DCCP, net); + return err; +} + +static void dccp_v4_exit_net(struct net *net) +{ + inet_ctl_sock_destroy(net->dccp.v4_ctl_sk); +} + +static struct pernet_operations dccp_v4_ops = { + .init = dccp_v4_init_net, + .exit = dccp_v4_exit_net, +}; + static int __init dccp_v4_init(void) { int err = proto_register(&dccp_v4_prot, 1); @@ -1005,13 +1023,12 @@ static int __init dccp_v4_init(void) inet_register_protosw(&dccp_v4_protosw); - err = inet_csk_ctl_sock_create(&dccp_v4_ctl_socket, PF_INET, - SOCK_DCCP, IPPROTO_DCCP); + err = register_pernet_subsys(&dccp_v4_ops); if (err) - goto out_unregister_protosw; + goto out_destroy_ctl_sock; out: return err; -out_unregister_protosw: +out_destroy_ctl_sock: inet_unregister_protosw(&dccp_v4_protosw); inet_del_protocol(&dccp_v4_protocol, IPPROTO_DCCP); out_proto_unregister: @@ -1021,6 +1038,7 @@ out_proto_unregister: static void __exit dccp_v4_exit(void) { + unregister_pernet_subsys(&dccp_v4_ops); inet_unregister_protosw(&dccp_v4_protosw); inet_del_protocol(&dccp_v4_protocol, IPPROTO_DCCP); proto_unregister(&dccp_v4_prot);