diff options
Diffstat (limited to 'net/ipv4')
41 files changed, 509 insertions, 368 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 09ca5293d08..44f5ce1fbfa 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -458,7 +458,7 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) err = -EADDRNOTAVAIL; if (!sysctl_ip_nonlocal_bind && !inet->freebind && - addr->sin_addr.s_addr != INADDR_ANY && + addr->sin_addr.s_addr != htonl(INADDR_ANY) && chk_addr_ret != RTN_LOCAL && chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST) @@ -784,6 +784,7 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { struct sock *sk = sock->sk; int err = 0; + struct net *net = sk->sk_net; switch (cmd) { case SIOCGSTAMP: @@ -795,12 +796,12 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCADDRT: case SIOCDELRT: case SIOCRTMSG: - err = ip_rt_ioctl(sk->sk_net, cmd, (void __user *)arg); + err = ip_rt_ioctl(net, cmd, (void __user *)arg); break; case SIOCDARP: case SIOCGARP: case SIOCSARP: - err = arp_ioctl(sk->sk_net, cmd, (void __user *)arg); + err = arp_ioctl(net, cmd, (void __user *)arg); break; case SIOCGIFADDR: case SIOCSIFADDR: @@ -813,7 +814,7 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCSIFPFLAGS: case SIOCGIFPFLAGS: case SIOCSIFFLAGS: - err = devinet_ioctl(cmd, (void __user *)arg); + err = devinet_ioctl(net, cmd, (void __user *)arg); break; default: if (sk->sk_prot->ioctl) @@ -1059,7 +1060,7 @@ static int inet_sk_reselect_saddr(struct sock *sk) if (sysctl_ip_dynaddr > 1) { printk(KERN_INFO "%s(): shifting inet->" "saddr from %d.%d.%d.%d to %d.%d.%d.%d\n", - __FUNCTION__, + __func__, NIPQUAD(old_saddr), NIPQUAD(new_saddr)); } @@ -1414,7 +1415,7 @@ static int __init inet_init(void) ip_init(); - tcp_v4_init(&inet_family_ops); + tcp_v4_init(); /* Setup TCP slab cache for open requests. */ tcp_init(); @@ -1429,7 +1430,8 @@ static int __init inet_init(void) * Set the ICMP layer up */ - icmp_init(&inet_family_ops); + if (icmp_init() < 0) + panic("Failed to create the ICMP control socket.\n"); /* * Initialise the multicast router diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 8e17f65f400..efe01df8fc0 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -475,7 +475,7 @@ int arp_find(unsigned char *haddr, struct sk_buff *skb) return 1; } - paddr = ((struct rtable*)skb->dst)->rt_gateway; + paddr = skb->rtable->rt_gateway; if (arp_set_predefined(inet_addr_type(&init_net, paddr), haddr, paddr, dev)) return 0; @@ -570,14 +570,13 @@ struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip, * Allocate a buffer */ - skb = alloc_skb(sizeof(struct arphdr)+ 2*(dev->addr_len+4) - + LL_RESERVED_SPACE(dev), GFP_ATOMIC); + skb = alloc_skb(arp_hdr_len(dev) + LL_RESERVED_SPACE(dev), GFP_ATOMIC); if (skb == NULL) return NULL; skb_reserve(skb, LL_RESERVED_SPACE(dev)); skb_reset_network_header(skb); - arp = (struct arphdr *) skb_put(skb,sizeof(struct arphdr) + 2*(dev->addr_len+4)); + arp = (struct arphdr *) skb_put(skb, arp_hdr_len(dev)); skb->dev = dev; skb->protocol = htons(ETH_P_ARP); if (src_hw == NULL) @@ -815,7 +814,7 @@ static int arp_process(struct sk_buff *skb) if (arp->ar_op == htons(ARPOP_REQUEST) && ip_route_input(skb, tip, sip, 0, dev) == 0) { - rt = (struct rtable*)skb->dst; + rt = skb->rtable; addr_type = rt->rt_type; if (addr_type == RTN_LOCAL) { @@ -916,9 +915,7 @@ static int arp_rcv(struct sk_buff *skb, struct net_device *dev, goto freeskb; /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ - if (!pskb_may_pull(skb, (sizeof(struct arphdr) + - (2 * dev->addr_len) + - (2 * sizeof(u32))))) + if (!pskb_may_pull(skb, arp_hdr_len(dev))) goto freeskb; arp = arp_hdr(skb); diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 8cd357f4128..4637ded3dba 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -1800,7 +1800,6 @@ int cipso_v4_sock_setattr(struct sock *sk, } memcpy(opt->__data, buf, buf_len); opt->optlen = opt_len; - opt->is_data = 1; opt->cipso = sizeof(struct iphdr); kfree(buf); buf = NULL; diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 87490f7bb0f..4a10dbbbe0a 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -446,9 +446,6 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg ASSERT_RTNL(); - if (net != &init_net) - return -EINVAL; - err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy); if (err < 0) goto errout; @@ -560,9 +557,6 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg ASSERT_RTNL(); - if (net != &init_net) - return -EINVAL; - ifa = rtm_to_ifaddr(net, nlh); if (IS_ERR(ifa)) return PTR_ERR(ifa); @@ -595,7 +589,7 @@ static __inline__ int inet_abc_len(__be32 addr) } -int devinet_ioctl(unsigned int cmd, void __user *arg) +int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg) { struct ifreq ifr; struct sockaddr_in sin_orig; @@ -624,7 +618,7 @@ int devinet_ioctl(unsigned int cmd, void __user *arg) *colon = 0; #ifdef CONFIG_KMOD - dev_load(&init_net, ifr.ifr_name); + dev_load(net, ifr.ifr_name); #endif switch (cmd) { @@ -665,7 +659,7 @@ int devinet_ioctl(unsigned int cmd, void __user *arg) rtnl_lock(); ret = -ENODEV; - if ((dev = __dev_get_by_name(&init_net, ifr.ifr_name)) == NULL) + if ((dev = __dev_get_by_name(net, ifr.ifr_name)) == NULL) goto done; if (colon) @@ -878,6 +872,7 @@ __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope) { __be32 addr = 0; struct in_device *in_dev; + struct net *net = dev->nd_net; rcu_read_lock(); in_dev = __in_dev_get_rcu(dev); @@ -906,7 +901,7 @@ no_in_dev: */ read_lock(&dev_base_lock); rcu_read_lock(); - for_each_netdev(&init_net, dev) { + for_each_netdev(net, dev) { if ((in_dev = __in_dev_get_rcu(dev)) == NULL) continue; @@ -1045,9 +1040,6 @@ static int inetdev_event(struct notifier_block *this, unsigned long event, struct net_device *dev = ptr; struct in_device *in_dev = __in_dev_get_rtnl(dev); - if (dev->nd_net != &init_net) - return NOTIFY_DONE; - ASSERT_RTNL(); if (!in_dev) { @@ -1173,9 +1165,6 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) struct in_ifaddr *ifa; int s_ip_idx, s_idx = cb->args[0]; - if (net != &init_net) - return 0; - s_ip_idx = ip_idx = cb->args[1]; idx = 0; for_each_netdev(net, dev) { diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 091e6709f83..f3ceca31aa4 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -168,7 +168,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) struct xfrm_encap_tmpl *encap = x->encap; struct udphdr *uh; __be32 *udpdata32; - unsigned int sport, dport; + __be16 sport, dport; int encap_type; spin_lock_bh(&x->lock); diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index a13c074dac0..ff9a8e643fc 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -229,14 +229,16 @@ static const struct icmp_control icmp_pointers[NR_ICMP_TYPES+1]; * * On SMP we have one ICMP socket per-cpu. */ -static DEFINE_PER_CPU(struct socket *, __icmp_socket) = NULL; -#define icmp_socket __get_cpu_var(__icmp_socket) +static struct sock *icmp_sk(struct net *net) +{ + return net->ipv4.icmp_sk[smp_processor_id()]; +} -static inline int icmp_xmit_lock(void) +static inline int icmp_xmit_lock(struct sock *sk) { local_bh_disable(); - if (unlikely(!spin_trylock(&icmp_socket->sk->sk_lock.slock))) { + if (unlikely(!spin_trylock(&sk->sk_lock.slock))) { /* This can happen if the output path signals a * dst_link_failure() for an outgoing ICMP packet. */ @@ -246,9 +248,9 @@ static inline int icmp_xmit_lock(void) return 0; } -static inline void icmp_xmit_unlock(void) +static inline void icmp_xmit_unlock(struct sock *sk) { - spin_unlock_bh(&icmp_socket->sk->sk_lock.slock); + spin_unlock_bh(&sk->sk_lock.slock); } /* @@ -346,19 +348,21 @@ static int icmp_glue_bits(void *from, char *to, int offset, int len, int odd, static void icmp_push_reply(struct icmp_bxm *icmp_param, struct ipcm_cookie *ipc, struct rtable *rt) { + struct sock *sk; struct sk_buff *skb; - if (ip_append_data(icmp_socket->sk, icmp_glue_bits, icmp_param, + sk = icmp_sk(rt->u.dst.dev->nd_net); + if (ip_append_data(sk, icmp_glue_bits, icmp_param, icmp_param->data_len+icmp_param->head_len, icmp_param->head_len, ipc, rt, MSG_DONTWAIT) < 0) - ip_flush_pending_frames(icmp_socket->sk); - else if ((skb = skb_peek(&icmp_socket->sk->sk_write_queue)) != NULL) { + ip_flush_pending_frames(sk); + else if ((skb = skb_peek(&sk->sk_write_queue)) != NULL) { struct icmphdr *icmph = icmp_hdr(skb); __wsum csum = 0; struct sk_buff *skb1; - skb_queue_walk(&icmp_socket->sk->sk_write_queue, skb1) { + skb_queue_walk(&sk->sk_write_queue, skb1) { csum = csum_add(csum, skb1->csum); } csum = csum_partial_copy_nocheck((void *)&icmp_param->data, @@ -366,7 +370,7 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param, icmp_param->head_len, csum); icmph->checksum = csum_fold(csum); skb->ip_summed = CHECKSUM_NONE; - ip_push_pending_frames(icmp_socket->sk); + ip_push_pending_frames(sk); } } @@ -376,16 +380,17 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param, static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) { - struct sock *sk = icmp_socket->sk; - struct inet_sock *inet = inet_sk(sk); struct ipcm_cookie ipc; - struct rtable *rt = (struct rtable *)skb->dst; + struct rtable *rt = skb->rtable; + struct net *net = rt->u.dst.dev->nd_net; + struct sock *sk = icmp_sk(net); + struct inet_sock *inet = inet_sk(sk); __be32 daddr; if (ip_options_echo(&icmp_param->replyopts, skb)) return; - if (icmp_xmit_lock()) + if (icmp_xmit_lock(sk)) return; icmp_param->data.icmph.checksum = 0; @@ -405,7 +410,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) .tos = RT_TOS(ip_hdr(skb)->tos) } }, .proto = IPPROTO_ICMP }; security_skb_classify_flow(skb, &fl); - if (ip_route_output_key(rt->u.dst.dev->nd_net, &rt, &fl)) + if (ip_route_output_key(net, &rt, &fl)) goto out_unlock; } if (icmpv4_xrlim_allow(rt, icmp_param->data.icmph.type, @@ -413,7 +418,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) icmp_push_reply(icmp_param, &ipc, rt); ip_rt_put(rt); out_unlock: - icmp_xmit_unlock(); + icmp_xmit_unlock(sk); } @@ -433,15 +438,17 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) struct iphdr *iph; int room; struct icmp_bxm icmp_param; - struct rtable *rt = (struct rtable *)skb_in->dst; + struct rtable *rt = skb_in->rtable; struct ipcm_cookie ipc; __be32 saddr; u8 tos; struct net *net; + struct sock *sk; if (!rt) goto out; net = rt->u.dst.dev->nd_net; + sk = icmp_sk(net); /* * Find the original header. It is expected to be valid, of course. @@ -505,7 +512,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) } } - if (icmp_xmit_lock()) + if (icmp_xmit_lock(sk)) return; /* @@ -544,7 +551,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) icmp_param.data.icmph.checksum = 0; icmp_param.skb = skb_in; icmp_param.offset = skb_network_offset(skb_in); - inet_sk(icmp_socket->sk)->tos = tos; + inet_sk(sk)->tos = tos; ipc.addr = iph->saddr; ipc.opt = &icmp_param.replyopts; @@ -609,7 +616,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) RT_TOS(tos), rt2->u.dst.dev); dst_release(&rt2->u.dst); - rt2 = (struct rtable *)skb_in->dst; + rt2 = skb_in->rtable; skb_in->dst = odst; } @@ -652,7 +659,7 @@ route_done: ende: ip_rt_put(rt); out_unlock: - icmp_xmit_unlock(); + icmp_xmit_unlock(sk); out:; } @@ -936,7 +943,7 @@ static void icmp_address(struct sk_buff *skb) static void icmp_address_reply(struct sk_buff *skb) { - struct rtable *rt = (struct rtable *)skb->dst; + struct rtable *rt = skb->rtable; struct net_device *dev = skb->dev; struct in_device *in_dev; struct in_ifaddr *ifa; @@ -981,7 +988,7 @@ static void icmp_discard(struct sk_buff *skb) int icmp_rcv(struct sk_buff *skb) { struct icmphdr *icmph; - struct rtable *rt = (struct rtable *)skb->dst; + struct rtable *rt = skb->rtable; if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { int nh; @@ -1139,29 +1146,46 @@ static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = { }, }; -void __init icmp_init(struct net_proto_family *ops) +static void __net_exit icmp_sk_exit(struct net *net) { - struct inet_sock *inet; int i; - for_each_possible_cpu(i) { - int err; + for_each_possible_cpu(i) + sk_release_kernel(net->ipv4.icmp_sk[i]); + kfree(net->ipv4.icmp_sk); + net->ipv4.icmp_sk = NULL; +} - err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP, - &per_cpu(__icmp_socket, i)); +int __net_init icmp_sk_init(struct net *net) +{ + int i, err; + net->ipv4.icmp_sk = + kzalloc(nr_cpu_ids * sizeof(struct sock *), GFP_KERNEL); + if (net->ipv4.icmp_sk == NULL) + return -ENOMEM; + + for_each_possible_cpu(i) { + struct sock *sk; + struct socket *sock; + struct inet_sock *inet; + + err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP, &sock); if (err < 0) - panic("Failed to create the ICMP control socket.\n"); + goto fail; + + net->ipv4.icmp_sk[i] = sk = sock->sk; + sk_change_net(sk, net); - per_cpu(__icmp_socket, i)->sk->sk_allocation = GFP_ATOMIC; + sk->sk_allocation = GFP_ATOMIC; /* Enough space for 2 64K ICMP packets, including * sk_buff struct overhead. */ - per_cpu(__icmp_socket, i)->sk->sk_sndbuf = + sk->sk_sndbuf = (2 * ((64 * 1024) + sizeof(struct sk_buff))); - inet = inet_sk(per_cpu(__icmp_socket, i)->sk); + inet = inet_sk(sk); inet->uc_ttl = -1; inet->pmtudisc = IP_PMTUDISC_DONT; @@ -1169,8 +1193,25 @@ void __init icmp_init(struct net_proto_family *ops) * see it, we do not wish this socket to see incoming * packets. */ - per_cpu(__icmp_socket, i)->sk->sk_prot->unhash(per_cpu(__icmp_socket, i)->sk); + sk->sk_prot->unhash(sk); } + return 0; + +fail: + for_each_possible_cpu(i) + sk_release_kernel(net->ipv4.icmp_sk[i]); + kfree(net->ipv4.icmp_sk); + return err; +} + +static struct pernet_operations __net_initdata icmp_sk_ops = { + .init = icmp_sk_init, + .exit = icmp_sk_exit, +}; + +int __init icmp_init(void) +{ + return register_pernet_device(&icmp_sk_ops); } EXPORT_SYMBOL(icmp_err_convert); diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 732cd07e607..6a4ee8da699 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -948,7 +948,7 @@ int igmp_rcv(struct sk_buff *skb) case IGMPV2_HOST_MEMBERSHIP_REPORT: case IGMPV3_HOST_MEMBERSHIP_REPORT: /* Is it our report looped back? */ - if (((struct rtable*)skb->dst)->fl.iif == 0) + if (skb->rtable->fl.iif == 0) break; /* don't rely on MC router hearing unicast reports */ if (skb->pkt_type == PACKET_MULTICAST || @@ -1198,6 +1198,9 @@ void ip_mc_inc_group(struct in_device *in_dev, __be32 addr) ASSERT_RTNL(); + if (in_dev->dev->nd_net != &init_net) + return; + for (im=in_dev->mc_list; im; im=im->next) { if (im->multiaddr == addr) { im->users++; @@ -1277,6 +1280,9 @@ void ip_mc_dec_group(struct in_device *in_dev, __be32 addr) ASSERT_RTNL(); + if (in_dev->dev->nd_net != &init_net) + return; + for (ip=&in_dev->mc_list; (i=*ip)!=NULL; ip=&i->next) { if (i->multiaddr==addr) { if (--i->users == 0) { @@ -1304,6 +1310,9 @@ void ip_mc_down(struct in_device *in_dev) ASSERT_RTNL(); + if (in_dev->dev->nd_net != &init_net) + return; + for (i=in_dev->mc_list; i; i=i->next) igmp_group_dropped(i); @@ -1324,6 +1333,9 @@ void ip_mc_init_dev(struct in_device *in_dev) { ASSERT_RTNL(); + if (in_dev->dev->nd_net != &init_net) + return; + in_dev->mc_tomb = NULL; #ifdef CONFIG_IP_MULTICAST in_dev->mr_gq_running = 0; @@ -1347,6 +1359,9 @@ void ip_mc_up(struct in_device *in_dev) ASSERT_RTNL(); + if (in_dev->dev->nd_net != &init_net) + return; + ip_mc_inc_group(in_dev, IGMP_ALL_HOSTS); for (i=in_dev->mc_list; i; i=i->next) @@ -1363,6 +1378,9 @@ void ip_mc_destroy_dev(struct in_device *in_dev) ASSERT_RTNL(); + if (in_dev->dev->nd_net != &init_net) + return; + /* Deactivate timers */ ip_mc_down(in_dev); @@ -1744,6 +1762,9 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr) if (!ipv4_is_multicast(addr)) return -EINVAL; + if (sk->sk_net != &init_net) + return -EPROTONOSUPPORT; + rtnl_lock(); in_dev = ip_mc_find_dev(imr); @@ -1812,6 +1833,9 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr) u32 ifindex; int ret = -EADDRNOTAVAIL; + if (sk->sk_net != &init_net) + return -EPROTONOSUPPORT; + rtnl_lock(); in_dev = ip_mc_find_dev(imr); ifindex = imr->imr_ifindex; @@ -1857,6 +1881,9 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct if (!ipv4_is_multicast(addr)) return -EINVAL; + if (sk->sk_net != &init_net) + return -EPROTONOSUPPORT; + rtnl_lock(); imr.imr_multiaddr.s_addr = mreqs->imr_multiaddr; @@ -1990,6 +2017,9 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex) msf->imsf_fmode != MCAST_EXCLUDE) return -EINVAL; + if (sk->sk_net != &init_net) + return -EPROTONOSUPPORT; + rtnl_lock(); imr.imr_multiaddr.s_addr = msf->imsf_multiaddr; @@ -2070,6 +2100,9 @@ int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf, if (!ipv4_is_multicast(addr)) return -EINVAL; + if (sk->sk_net != &init_net) + return -EPROTONOSUPPORT; + rtnl_lock(); imr.imr_multiaddr.s_addr = msf->imsf_multiaddr; @@ -2132,6 +2165,9 @@ int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf, if (!ipv4_is_multicast(addr)) return -EINVAL; + if (sk->sk_net != &init_net) + return -EPROTONOSUPPORT; + rtnl_lock(); err = -EADDRNOTAVAIL; @@ -2216,6 +2252,9 @@ void ip_mc_drop_socket(struct sock *sk) if (inet->mc_list == NULL) return; + if (sk->sk_net != &init_net) + return; + rtnl_lock(); while ((iml = inet->mc_list) != NULL) { struct in_device *in_dev; diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index b189278c7bc..f9c5c4def1b 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -80,7 +80,7 @@ EXPORT_SYMBOL_GPL(inet_csk_bind_conflict); */ int inet_csk_get_port(struct sock *sk, unsigned short snum) { - struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo; + struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo; struct inet_bind_hashbucket *head; struct hlist_node *node; struct inet_bind_bucket *tb; @@ -414,8 +414,7 @@ void inet_csk_reqsk_queue_prune(struct sock *parent, struct inet_connection_sock *icsk = inet_csk(parent); struct request_sock_queue *queue = &icsk->icsk_accept_queue; struct listen_sock *lopt = queue->listen_opt; - int max_retries = icsk->icsk_syn_retries ? : sysctl_tcp_synack_retries; - int thresh = max_retries; + int thresh = icsk->icsk_syn_retries ? : sysctl_tcp_synack_retries; unsigned long now = jiffies; struct request_sock **reqp, *req; int i, budget; @@ -451,9 +450,6 @@ void inet_csk_reqsk_queue_prune(struct sock *parent, } } - if (queue->rskq_defer_accept) - max_retries = queue->rskq_defer_accept; - budget = 2 * (lopt->nr_table_entries / (timeout / interval)); i = lopt->clock_hand; @@ -461,9 +457,8 @@ void inet_csk_reqsk_queue_prune(struct sock *parent, reqp=&lopt->syn_table[i]; while ((req = *reqp) != NULL) { if (time_after_eq(now, req->expires)) { - if ((req->retrans < thresh || - (inet_rsk(req)->acked && req->retrans < max_retries)) - && !req->rsk_ops->rtx_syn_ack(parent, req, NULL)) { + if (req->retrans < thresh && + !req->rsk_ops->rtx_syn_ack(parent, req)) { unsigned long timeo; if (req->retrans++ == 0) diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 1aba606f6bb..8cd1ad9b911 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -68,7 +68,7 @@ void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb, */ static void __inet_put_port(struct sock *sk) { - struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo; + struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo; const int bhash = inet_bhashfn(inet_sk(sk)->num, hashinfo->bhash_size); struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash]; struct inet_bind_bucket *tb; @@ -318,7 +318,7 @@ static inline u32 inet_sk_port_offset(const struct sock *sk) void __inet_hash_nolisten(struct sock *sk) { - struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo; + struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo; struct hlist_head *list; rwlock_t *lock; struct inet_ehash_bucket *head; @@ -339,7 +339,7 @@ EXPORT_SYMBOL_GPL(__inet_hash_nolisten); static void __inet_hash(struct sock *sk) { - struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo; + struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo; struct hlist_head *list; rwlock_t *lock; @@ -372,7 +372,7 @@ EXPORT_SYMBOL_GPL(inet_hash); void inet_unhash(struct sock *sk) { rwlock_t *lock; - struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo; + struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo; if (sk_unhashed(sk)) goto out; diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c index 876169f3a52..717c411a5c6 100644 --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c @@ -124,6 +124,7 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int stat tw->tw_hash = sk->sk_hash; tw->tw_ipv6only = 0; tw->tw_prot = sk->sk_prot_creator; + tw->tw_net = sk->sk_net; atomic_set(&tw->tw_refcnt, 1); inet_twsk_dead_node_init(tw); __module_get(tw->tw_prot->owner); diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index 0b3b328d82d..9d6d3befd85 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -80,7 +80,7 @@ int ip_forward(struct sk_buff *skb) if (!xfrm4_route_forward(skb)) goto drop; - rt = (struct rtable*)skb->dst; + rt = skb->rtable; if (opt->is_strictroute && rt->rt_dst != rt->rt_gateway) goto sr_failed; diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index e7821ba7a9a..f9ee84420cb 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -619,7 +619,7 @@ static int ipgre_rcv(struct sk_buff *skb) #ifdef CONFIG_NET_IPGRE_BROADCAST if (ipv4_is_multicast(iph->daddr)) { /* Looped back packet, drop it! */ - if (((struct rtable*)skb->dst)->fl.iif == 0) + if (skb->rtable->fl.iif == 0) goto drop; tunnel->stat.multicast++; skb->pkt_type = PACKET_BROADCAST; @@ -699,7 +699,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) } if (skb->protocol == htons(ETH_P_IP)) { - rt = (struct rtable*)skb->dst; + rt = skb->rtable; if ((dst = rt->rt_gateway) == 0) goto tx_error_icmp; } diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 65631391d47..e3a0c78fa7b 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -283,13 +283,14 @@ static inline int ip_rcv_options(struct sk_buff *skb) } iph = ip_hdr(skb); + opt = &(IPCB(skb)->opt); + opt->optlen = iph->ihl*4 - sizeof(struct iphdr); - if (ip_options_compile(NULL, skb)) { + if (ip_options_compile(opt, skb)) { IP_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); goto drop; } - opt = &(IPCB(skb)->opt); if (unlikely(opt->srr)) { struct in_device *in_dev = in_dev_get(dev); if (in_dev) { @@ -351,7 +352,7 @@ static int ip_rcv_finish(struct sk_buff *skb) if (iph->ihl > 5 && ip_rcv_options(skb)) goto drop; - rt = (struct rtable*)skb->dst; + rt = skb->rtable; if (rt->rt_type == RTN_MULTICAST) IP_INC_STATS_BH(IPSTATS_MIB_INMCASTPKTS); else if (rt->rt_type == RTN_BROADCAST) diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index 4d315158fd3..aeed4e5858e 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -45,7 +45,6 @@ void ip_options_build(struct sk_buff * skb, struct ip_options * opt, memcpy(&(IPCB(skb)->opt), opt, sizeof(struct ip_options)); memcpy(iph+sizeof(struct iphdr), opt->__data, opt->optlen); opt = &(IPCB(skb)->opt); - opt->is_data = 0; if (opt->srr) memcpy(iph+opt->srr+iph[opt->srr+1]-4, &daddr, 4); @@ -95,8 +94,6 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb) memset(dopt, 0, sizeof(struct ip_options)); - dopt->is_data = 1; - sopt = &(IPCB(skb)->opt); if (sopt->optlen == 0) { @@ -107,10 +104,7 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb) sptr = skb_network_header(skb); dptr = dopt->__data; - if (skb->dst) - daddr = ((struct rtable*)skb->dst)->rt_spec_dst; - else - daddr = ip_hdr(skb)->daddr; + daddr = skb->rtable->rt_spec_dst; if (sopt->rr) { optlen = sptr[sopt->rr+1]; @@ -261,19 +255,14 @@ int ip_options_compile(struct ip_options * opt, struct sk_buff * skb) unsigned char * optptr; int optlen; unsigned char * pp_ptr = NULL; - struct rtable *rt = skb ? (struct rtable*)skb->dst : NULL; - - if (!opt) { - opt = &(IPCB(skb)->opt); - iph = skb_network_header(skb); - opt->optlen = ((struct iphdr *)iph)->ihl*4 - sizeof(struct iphdr); - optptr = iph + sizeof(struct iphdr); - opt->is_data = 0; - } else { - optptr = opt->is_data ? opt->__data : - (unsigned char *)&(ip_hdr(skb)[1]); - iph = optptr - sizeof(struct iphdr); - } + struct rtable *rt = NULL; + + if (skb != NULL) { + rt = skb->rtable; + optptr = (unsigned char *)&(ip_hdr(skb)[1]); + } else + optptr = opt->__data; + iph = optptr - sizeof(struct iphdr); for (l = opt->optlen; l > 0; ) { switch (*optptr) { @@ -523,7 +512,6 @@ static int ip_options_get_finish(struct ip_options **optp, while (optlen & 3) opt->__data[optlen++] = IPOPT_END; opt->optlen = optlen; - opt->is_data = 1; if (optlen && ip_options_compile(opt, NULL)) { kfree(opt); return -EINVAL; @@ -561,7 +549,7 @@ void ip_forward_options(struct sk_buff *skb) { struct ip_options * opt = &(IPCB(skb)->opt); unsigned char * optptr; - struct rtable *rt = (struct rtable*)skb->dst; + struct rtable *rt = skb->rtable; unsigned char *raw = skb_network_header(skb); if (opt->rr_needaddr) { @@ -609,7 +597,7 @@ int ip_options_rcv_srr(struct sk_buff *skb) __be32 nexthop; struct iphdr *iph = ip_hdr(skb); unsigned char *optptr = skb_network_header(skb) + opt->srr; - struct rtable *rt = (struct rtable*)skb->dst; + struct rtable *rt = skb->rtable; struct rtable *rt2; int err; @@ -634,13 +622,13 @@ int ip_options_rcv_srr(struct sk_buff *skb) } memcpy(&nexthop, &optptr[srrptr-1], 4); - rt = (struct rtable*)skb->dst; - skb->dst = NULL; + rt = skb->rtable; + skb->rtable = NULL; err = ip_route_input(skb, nexthop, iph->saddr, iph->tos, skb->dev); - rt2 = (struct rtable*)skb->dst; + rt2 = skb->rtable; if (err || (rt2->rt_type != RTN_UNICAST && rt2->rt_type != RTN_LOCAL)) { ip_rt_put(rt2); - skb->dst = &rt->u.dst; + skb->rtable = rt; return -EINVAL; } ip_rt_put(rt); diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 341779e685d..dc494ea594a 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -142,7 +142,7 @@ int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk, __be32 saddr, __be32 daddr, struct ip_options *opt) { struct inet_sock *inet = inet_sk(sk); - struct rtable *rt = (struct rtable *)skb->dst; + struct rtable *rt = skb->rtable; struct iphdr *iph; /* Build the IP header. */ @@ -240,7 +240,7 @@ static int ip_finish_output(struct sk_buff *skb) int ip_mc_output(struct sk_buff *skb) { struct sock *sk = skb->sk; - struct rtable *rt = (struct rtable*)skb->dst; + struct rtable *rt = skb->rtable; struct net_device *dev = rt->u.dst.dev; /* @@ -321,7 +321,7 @@ int ip_queue_xmit(struct sk_buff *skb, int ipfragok) /* Skip all of this if the packet is already routed, * f.e. by something like SCTP. */ - rt = (struct rtable *) skb->dst; + rt = skb->rtable; if (rt != NULL) goto packet_routed; @@ -441,7 +441,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) unsigned int mtu, hlen, left, len, ll_rs, pad; int offset; __be16 not_last_frag; - struct rtable *rt = (struct rtable*)skb->dst; + struct rtable *rt = skb->rtable; int err = 0; dev = rt->u.dst.dev; @@ -1357,7 +1357,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar } replyopts; struct ipcm_cookie ipc; __be32 daddr; - struct rtable *rt = (struct rtable*)skb->dst; + struct rtable *rt = skb->rtable; if (ip_options_echo(&replyopts.opt, skb)) return; diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index de0572c8885..bb3cbe5ec36 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -57,7 +57,7 @@ static void ip_cmsg_recv_pktinfo(struct msghdr *msg, struct sk_buff *skb) { struct in_pktinfo info; - struct rtable *rt = (struct rtable *)skb->dst; + struct rtable *rt = skb->rtable; info.ipi_addr.s_addr = ip_hdr(skb)->daddr; if (rt) { @@ -583,7 +583,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, } if (!mreq.imr_ifindex) { - if (mreq.imr_address.s_addr == INADDR_ANY) { + if (mreq.imr_address.s_addr == htonl(INADDR_ANY)) { inet->mc_index = 0; inet->mc_addr = 0; err = 0; diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 5dd938579ee..96138b128de 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -103,6 +103,7 @@ - '3' from resolv.h */ #define NONE __constant_htonl(INADDR_NONE) +#define ANY __constant_htonl(INADDR_ANY) /* * Public IP configuration @@ -291,7 +292,7 @@ static int __init ic_dev_ioctl(unsigned int cmd, struct ifreq *arg) mm_segment_t oldfs = get_fs(); set_fs(get_ds()); - res = devinet_ioctl(cmd, (struct ifreq __user *) arg); + res = devinet_ioctl(&init_net, cmd, (struct ifreq __user *) arg); set_fs(oldfs); return res; } @@ -459,10 +460,7 @@ ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt if (rarp->ar_pro != htons(ETH_P_IP)) goto drop; - if (!pskb_may_pull(skb, - sizeof(struct arphdr) + - (2 * dev->addr_len) + - (2 * 4))) + if (!pskb_may_pull(skb, arp_hdr_len(dev))) goto drop; /* OK, it is all there and looks valid, process... */ @@ -1479,19 +1477,19 @@ static int __init ip_auto_config_setup(char *addrs) DBG(("IP-Config: Parameter #%d: `%s'\n", num, ip)); switch (num) { case 0: - if ((ic_myaddr = in_aton(ip)) == INADDR_ANY) + if ((ic_myaddr = in_aton(ip)) == ANY) ic_myaddr = NONE; break; case 1: - if ((ic_servaddr = in_aton(ip)) == INADDR_ANY) + if ((ic_servaddr = in_aton(ip)) == ANY) ic_servaddr = NONE; break; case 2: - if ((ic_gateway = in_aton(ip)) == INADDR_ANY) + if ((ic_gateway = in_aton(ip)) == ANY) ic_gateway = NONE; break; case 3: - if ((ic_netmask = in_aton(ip)) == INADDR_ANY) + if ((ic_netmask = in_aton(ip)) == ANY) ic_netmask = NONE; break; case 4: diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index dbaed69de06..894bce96284 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -528,7 +528,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) if (!dst) { /* NBMA tunnel */ - if ((rt = (struct rtable*)skb->dst) == NULL) { + if ((rt = skb->rtable) == NULL) { tunnel->stat.tx_fifo_errors++; goto tx_error; } diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index a94f52c207a..7d63d74ef62 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1283,7 +1283,7 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local if (vif_table[vif].dev != skb->dev) { int true_vifi; - if (((struct rtable*)skb->dst)->fl.iif == 0) { + if (skb->rtable->fl.iif == 0) { /* It is our own packet, looped back. Very complicated situation... @@ -1357,7 +1357,7 @@ dont_forward: int ip_mr_input(struct sk_buff *skb) { struct mfc_cache *cache; - int local = ((struct rtable*)skb->dst)->rt_flags&RTCF_LOCAL; + int local = skb->rtable->rt_flags&RTCF_LOCAL; /* Packet is looped back after forward, it should not be forwarded second time, but still can be delivered locally. @@ -1594,7 +1594,7 @@ int ipmr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait) { int err; struct mfc_cache *cache; - struct rtable *rt = (struct rtable*)skb->dst; + struct rtable *rt = skb->rtable; read_lock(&mrt_lock); cache = ipmr_cache_find(rt->rt_src, rt->rt_dst); diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c index 12dc0d640b6..620e40ff79a 100644 --- a/net/ipv4/ipvs/ip_vs_proto_tcp.c +++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c @@ -550,7 +550,7 @@ tcp_app_conn_bind(struct ip_vs_conn *cp) IP_VS_DBG(9, "%s: Binding conn %u.%u.%u.%u:%u->" "%u.%u.%u.%u:%u to app %s on port %u\n", - __FUNCTION__, + __func__, NIPQUAD(cp->caddr), ntohs(cp->cport), NIPQUAD(cp->vaddr), ntohs(cp->vport), inc->name, ntohs(inc->port)); diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c index 1fa7b330b9a..1caa2908373 100644 --- a/net/ipv4/ipvs/ip_vs_proto_udp.c +++ b/net/ipv4/ipvs/ip_vs_proto_udp.c @@ -344,7 +344,7 @@ static int udp_app_conn_bind(struct ip_vs_conn *cp) IP_VS_DBG(9, "%s: Binding conn %u.%u.%u.%u:%u->" "%u.%u.%u.%u:%u to app %s on port %u\n", - __FUNCTION__, + __func__, NIPQUAD(cp->caddr), ntohs(cp->cport), NIPQUAD(cp->vaddr), ntohs(cp->vport), inc->name, ntohs(inc->port)); diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c index 948378d0a75..69c56663cc9 100644 --- a/net/ipv4/ipvs/ip_vs_sync.c +++ b/net/ipv4/ipvs/ip_vs_sync.c @@ -916,7 +916,7 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid) if (!tinfo) return -ENOMEM; - IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, task_pid_nr(current)); + IP_VS_DBG(7, "%s: pid %d\n", __func__, task_pid_nr(current)); IP_VS_DBG(7, "Each ip_vs_sync_conn entry need %Zd bytes\n", sizeof(struct ip_vs_sync_conn)); @@ -956,7 +956,7 @@ int stop_sync_thread(int state) (state == IP_VS_STATE_BACKUP && !sync_backup_pid)) return -ESRCH; - IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, task_pid_nr(current)); + IP_VS_DBG(7, "%s: pid %d\n", __func__, task_pid_nr(current)); IP_VS_INFO("stopping sync thread %d ...\n", (state == IP_VS_STATE_MASTER) ? sync_master_pid : sync_backup_pid); diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index a7591ce344d..756bc0e1a7c 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -52,7 +52,7 @@ MODULE_DESCRIPTION("arptables core"); do { \ if (!(x)) \ printk("ARP_NF_ASSERT: %s:%s:%u\n", \ - __FUNCTION__, __FILE__, __LINE__); \ + __func__, __FILE__, __LINE__); \ } while(0) #else #define ARP_NF_ASSERT(x) @@ -233,10 +233,7 @@ unsigned int arpt_do_table(struct sk_buff *skb, void *table_base; struct xt_table_info *private; - /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ - if (!pskb_may_pull(skb, (sizeof(struct arphdr) + - (2 * skb->dev->addr_len) + - (2 * sizeof(u32))))) + if (!pskb_may_pull(skb, arp_hdr_len(skb->dev))) return NF_DROP; indev = in ? in->name : nulldevname; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 600737f122d..85a75e186b4 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -53,7 +53,7 @@ MODULE_DESCRIPTION("IPv4 packet filter"); do { \ if (!(x)) \ printk("IP_NF_ASSERT: %s:%s:%u\n", \ - __FUNCTION__, __FILE__, __LINE__); \ + __func__, __FILE__, __LINE__); \ } while(0) #else #define IP_NF_ASSERT(x) diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index d80fee8327e..c6817b18366 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c @@ -77,7 +77,7 @@ masquerade_tg(struct sk_buff *skb, const struct net_device *in, return NF_ACCEPT; mr = targinfo; - rt = (struct rtable *)skb->dst; + rt = skb->rtable; newsrc = inet_select_addr(out, rt->rt_gateway, RT_SCOPE_UNIVERSE); if (!newsrc) { printk("MASQUERADE: %s ate my IP address\n", out->name); @@ -139,18 +139,8 @@ static int masq_inet_event(struct notifier_block *this, unsigned long event, void *ptr) { - const struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev; - - if (event == NETDEV_DOWN) { - /* IP address was deleted. Search entire table for - conntracks which were associated with that device, - and forget them. */ - NF_CT_ASSERT(dev->ifindex != 0); - - nf_ct_iterate_cleanup(device_cmp, (void *)(long)dev->ifindex); - } - - return NOTIFY_DONE; + struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev; + return masq_device_event(this, event, dev); } static struct notifier_block masq_dev_notifier = { diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c index 68cbe3ca01c..8e8f0425a8e 100644 --- a/net/ipv4/netfilter/ipt_recent.c +++ b/net/ipv4/netfilter/ipt_recent.c @@ -252,6 +252,8 @@ recent_mt_check(const char *tablename, const void *ip, if ((info->check_set & (IPT_RECENT_SET | IPT_RECENT_REMOVE)) && (info->seconds || info->hit_count)) return false; + if (info->hit_count > ip_pkt_list_tot) + return false; if (info->name[0] == '\0' || strnlen(info->name, IPT_RECENT_NAME_LEN) == IPT_RECENT_NAME_LEN) return false; diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c index 089252e82c0..9668c3a23ef 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c @@ -379,7 +379,7 @@ static const struct file_operations ct_cpu_seq_fops = { .open = ct_cpu_seq_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release_private, + .release = seq_release, }; int __init nf_conntrack_ipv4_compat_init(void) diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index ca57f47bbd2..2fca727aa8b 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c @@ -139,7 +139,7 @@ nf_nat_mangle_tcp_packet(struct sk_buff *skb, const char *rep_buffer, unsigned int rep_len) { - struct rtable *rt = (struct rtable *)skb->dst; + struct rtable *rt = skb->rtable; struct iphdr *iph; struct tcphdr *tcph; int oldlen, datalen; @@ -217,7 +217,7 @@ nf_nat_mangle_udp_packet(struct sk_buff *skb, const char *rep_buffer, unsigned int rep_len) { - struct rtable *rt = (struct rtable *)skb->dst; + struct rtable *rt = skb->rtable; struct iphdr *iph; struct udphdr *udph; int datalen, oldlen; diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index a3002fe65b7..b433b485a88 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -81,11 +81,12 @@ #include <linux/netfilter_ipv4.h> static struct raw_hashinfo raw_v4_hashinfo = { - .lock = __RW_LOCK_UNLOCKED(), + .lock = __RW_LOCK_UNLOCKED(raw_v4_hashinfo.lock), }; -void raw_hash_sk(struct sock *sk, struct raw_hashinfo *h) +void raw_hash_sk(struct sock *sk) { + struct raw_hashinfo *h = sk->sk_prot->h.raw_hash; struct hlist_head *head; head = &h->ht[inet_sk(sk)->num & (RAW_HTABLE_SIZE - 1)]; @@ -97,8 +98,10 @@ void raw_hash_sk(struct sock *sk, struct raw_hashinfo *h) } EXPORT_SYMBOL_GPL(raw_hash_sk); -void raw_unhash_sk(struct sock *sk, struct raw_hashinfo *h) +void raw_unhash_sk(struct sock *sk) { + struct raw_hashinfo *h = sk->sk_prot->h.raw_hash; + write_lock_bh(&h->lock); if (sk_del_node_init(sk)) sock_prot_inuse_add(sk->sk_prot, -1); @@ -106,16 +109,6 @@ void raw_unhash_sk(struct sock *sk, struct raw_hashinfo *h) } EXPORT_SYMBOL_GPL(raw_unhash_sk); -static void raw_v4_hash(struct sock *sk) -{ - raw_hash_sk(sk, &raw_v4_hashinfo); -} - -static void raw_v4_unhash(struct sock *sk) -{ - raw_unhash_sk(sk, &raw_v4_hashinfo); -} - static struct sock *__raw_v4_lookup(struct net *net, struct sock *sk, unsigned short num, __be32 raddr, __be32 laddr, int dif) { @@ -841,9 +834,10 @@ struct proto raw_prot = { .recvmsg = raw_recvmsg, .bind = raw_bind, .backlog_rcv = raw_rcv_skb, - .hash = raw_v4_hash, - .unhash = raw_v4_unhash, + .hash = raw_hash_sk, + .unhash = raw_unhash_sk, .obj_size = sizeof(struct raw_sock), + .h.raw_hash = &raw_v4_hashinfo, #ifdef CONFIG_COMPAT .compat_setsockopt = compat_raw_setsockopt, .compat_getsockopt = compat_raw_getsockopt, diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 7b5e8e1d94b..2941ef21f20 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -118,21 +118,19 @@ #define RT_GC_TIMEOUT (300*HZ) static int ip_rt_max_size; -static int ip_rt_gc_timeout = RT_GC_TIMEOUT; -static int ip_rt_gc_interval = 60 * HZ; -static int ip_rt_gc_min_interval = HZ / 2; -static int ip_rt_redirect_number = 9; -static int ip_rt_redirect_load = HZ / 50; -static int ip_rt_redirect_silence = ((HZ / 50) << (9 + 1)); -static int ip_rt_error_cost = HZ; -static int ip_rt_error_burst = 5 * HZ; -static int ip_rt_gc_elasticity = 8; -static int ip_rt_mtu_expires = 10 * 60 * HZ; -static int ip_rt_min_pmtu = 512 + 20 + 20; -static int ip_rt_min_advmss = 256; -static int ip_rt_secret_interval = 10 * 60 * HZ; - -#define RTprint(a...) printk(KERN_DEBUG a) +static int ip_rt_gc_timeout __read_mostly = RT_GC_TIMEOUT; +static int ip_rt_gc_interval __read_mostly = 60 * HZ; +static int ip_rt_gc_min_interval __read_mostly = HZ / 2; +static int ip_rt_redirect_number __read_mostly = 9; +static int ip_rt_redirect_load __read_mostly = HZ / 50; +static int ip_rt_redirect_silence __read_mostly = ((HZ / 50) << (9 + 1)); +static int ip_rt_error_cost __read_mostly = HZ; +static int ip_rt_error_burst __read_mostly = 5 * HZ; +static int ip_rt_gc_elasticity __read_mostly = 8; +static int ip_rt_mtu_expires __read_mostly = 10 * 60 * HZ; +static int ip_rt_min_pmtu __read_mostly = 512 + 20 + 20; +static int ip_rt_min_advmss __read_mostly = 256; +static int ip_rt_secret_interval __read_mostly = 10 * 60 * HZ; static void rt_worker_func(struct work_struct *work); static DECLARE_DELAYED_WORK(expires_work, rt_worker_func); @@ -252,10 +250,10 @@ static inline void rt_hash_lock_init(void) } #endif -static struct rt_hash_bucket *rt_hash_table; -static unsigned rt_hash_mask; -static unsigned int rt_hash_log; -static atomic_t rt_genid; +static struct rt_hash_bucket *rt_hash_table __read_mostly; +static unsigned rt_hash_mask __read_mostly; +static unsigned int rt_hash_log __read_mostly; +static atomic_t rt_genid __read_mostly; static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat); #define RT_CACHE_STAT_INC(field) \ @@ -273,6 +271,7 @@ static unsigned int rt_hash_code(u32 daddr, u32 saddr) #ifdef CONFIG_PROC_FS struct rt_cache_iter_state { + struct seq_net_private p; int bucket; int genid; }; @@ -285,7 +284,8 @@ static struct rtable *rt_cache_get_first(struct rt_cache_iter_state *st) rcu_read_lock_bh(); r = rcu_dereference(rt_hash_table[st->bucket].chain); while (r) { - if (r->rt_genid == st->genid) + if (r->u.dst.dev->nd_net == st->p.net && + r->rt_genid == st->genid) return r; r = rcu_dereference(r->u.dst.rt_next); } @@ -294,7 +294,8 @@ static struct rtable *rt_cache_get_first(struct rt_cache_iter_state *st) return r; } -static struct rtable *rt_cache_get_next(struct rt_cache_iter_state *st, struct rtable *r) +static struct rtable *__rt_cache_get_next(struct rt_cache_iter_state *st, + struct rtable *r) { r = r->u.dst.rt_next; while (!r) { @@ -307,16 +308,25 @@ static struct rtable *rt_cache_get_next(struct rt_cache_iter_state *st, struct r return rcu_dereference(r); } +static struct rtable *rt_cache_get_next(struct rt_cache_iter_state *st, + struct rtable *r) +{ + while ((r = __rt_cache_get_next(st, r)) != NULL) { + if (r->u.dst.dev->nd_net != st->p.net) + continue; + if (r->rt_genid == st->genid) + break; + } + return r; +} + static struct rtable *rt_cache_get_idx(struct rt_cache_iter_state *st, loff_t pos) { struct rtable *r = rt_cache_get_first(st); if (r) - while (pos && (r = rt_cache_get_next(st, r))) { - if (r->rt_genid != st->genid) - continue; + while (pos && (r = rt_cache_get_next(st, r))) --pos; - } return pos ? NULL : r; } @@ -390,7 +400,7 @@ static const struct seq_operations rt_cache_seq_ops = { static int rt_cache_seq_open(struct inode *inode, struct file *file) { - return seq_open_private(file, &rt_cache_seq_ops, + return seq_open_net(inode, file, &rt_cache_seq_ops, sizeof(struct rt_cache_iter_state)); } @@ -399,7 +409,7 @@ static const struct file_operations rt_cache_seq_fops = { .open = rt_cache_seq_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release_private, + .release = seq_release_net, }; @@ -533,7 +543,7 @@ static int ip_rt_acct_read(char *buffer, char **start, off_t offset, } #endif -static __init int ip_rt_proc_init(struct net *net) +static int __net_init ip_rt_do_proc_init(struct net *net) { struct proc_dir_entry *pde; @@ -564,8 +574,26 @@ err2: err1: return -ENOMEM; } + +static void __net_exit ip_rt_do_proc_exit(struct net *net) +{ + remove_proc_entry("rt_cache", net->proc_net_stat); + remove_proc_entry("rt_cache", net->proc_net); + remove_proc_entry("rt_acct", net->proc_net); +} + +static struct pernet_operations ip_rt_proc_ops __net_initdata = { + .init = ip_rt_do_proc_init, + .exit = ip_rt_do_proc_exit, +}; + +static int __init ip_rt_proc_init(void) +{ + return register_pernet_subsys(&ip_rt_proc_ops); +} + #else -static inline int ip_rt_proc_init(struct net *net) +static inline int ip_rt_proc_init(void) { return 0; } @@ -1131,10 +1159,12 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, __be32 skeys[2] = { saddr, 0 }; int ikeys[2] = { dev->ifindex, 0 }; struct netevent_redirect netevent; + struct net *net; if (!in_dev) return; + net = dev->nd_net; if (new_gw == old_gw || !IN_DEV_RX_REDIRECTS(in_dev) || ipv4_is_multicast(new_gw) || ipv4_is_lbcast(new_gw) || ipv4_is_zeronet(new_gw)) @@ -1146,7 +1176,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, if (IN_DEV_SEC_REDIRECTS(in_dev) && ip_fib_check_default(new_gw, dev)) goto reject_redirect; } else { - if (inet_addr_type(&init_net, new_gw) != RTN_UNICAST) + if (inet_addr_type(net, new_gw) != RTN_UNICAST) goto reject_redirect; } @@ -1164,7 +1194,8 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, rth->fl.fl4_src != skeys[i] || rth->fl.oif != ikeys[k] || rth->fl.iif != 0 || - rth->rt_genid != atomic_read(&rt_genid)) { + rth->rt_genid != atomic_read(&rt_genid) || + rth->u.dst.dev->nd_net != net) { rthp = &rth->u.dst.rt_next; continue; } @@ -1256,7 +1287,7 @@ reject_redirect: static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) { - struct rtable *rt = (struct rtable*)dst; + struct rtable *rt = (struct rtable *)dst; struct dst_entry *ret = dst; if (rt) { @@ -1297,7 +1328,7 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) void ip_rt_send_redirect(struct sk_buff *skb) { - struct rtable *rt = (struct rtable*)skb->dst; + struct rtable *rt = skb->rtable; struct in_device *in_dev = in_dev_get(rt->u.dst.dev); if (!in_dev) @@ -1346,7 +1377,7 @@ out: static int ip_error(struct sk_buff *skb) { - struct rtable *rt = (struct rtable*)skb->dst; + struct rtable *rt = skb->rtable; unsigned long now; int code; @@ -1515,7 +1546,7 @@ static void ipv4_link_failure(struct sk_buff *skb) icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0); - rt = (struct rtable *) skb->dst; + rt = skb->rtable; if (rt) dst_set_expires(&rt->u.dst, 0); } @@ -1675,7 +1706,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, in_dev_put(in_dev); hash = rt_hash(daddr, saddr, dev->ifindex); - return rt_intern_hash(hash, rth, (struct rtable**) &skb->dst); + return rt_intern_hash(hash, rth, &skb->rtable); e_nobufs: in_dev_put(in_dev); @@ -1836,7 +1867,7 @@ static inline int ip_mkroute_input(struct sk_buff *skb, /* put it into the cache */ hash = rt_hash(daddr, saddr, fl->iif); - return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst); + return rt_intern_hash(hash, rth, &skb->rtable); } /* @@ -1992,7 +2023,7 @@ local_input: } rth->rt_type = res.type; hash = rt_hash(daddr, saddr, fl.iif); - err = rt_intern_hash(hash, rth, (struct rtable**)&skb->dst); + err = rt_intern_hash(hash, rth, &skb->rtable); goto done; no_route: @@ -2058,7 +2089,7 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr, dst_use(&rth->u.dst, jiffies); RT_CACHE_STAT_INC(in_hit); rcu_read_unlock(); - skb->dst = (struct dst_entry*)rth; + skb->rtable = rth; return 0; } RT_CACHE_STAT_INC(in_hlist_search); @@ -2487,7 +2518,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = { }; -static int ipv4_dst_blackhole(struct rtable **rp, struct flowi *flp, struct sock *sk) +static int ipv4_dst_blackhole(struct rtable **rp, struct flowi *flp) { struct rtable *ort = *rp; struct rtable *rt = (struct rtable *) @@ -2547,7 +2578,7 @@ int ip_route_output_flow(struct net *net, struct rtable **rp, struct flowi *flp, err = __xfrm_lookup((struct dst_entry **)rp, flp, sk, flags ? XFRM_LOOKUP_WAIT : 0); if (err == -EREMOTE) - err = ipv4_dst_blackhole(rp, flp, sk); + err = ipv4_dst_blackhole(rp, flp); return err; } @@ -2565,7 +2596,7 @@ int ip_route_output_key(struct net *net, struct rtable **rp, struct flowi *flp) static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, int nowait, unsigned int flags) { - struct rtable *rt = (struct rtable*)skb->dst; + struct rtable *rt = skb->rtable; struct rtmsg *r; struct nlmsghdr *nlh; long expires; @@ -2668,9 +2699,6 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void int err; struct sk_buff *skb; - if (net != &init_net) - return -EINVAL; - err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv4_policy); if (err < 0) goto errout; @@ -2700,7 +2728,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void if (iif) { struct net_device *dev; - dev = __dev_get_by_index(&init_net, iif); + dev = __dev_get_by_index(net, iif); if (dev == NULL) { err = -ENODEV; goto errout_free; @@ -2712,7 +2740,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void err = ip_route_input(skb, dst, src, rtm->rtm_tos, dev); local_bh_enable(); - rt = (struct rtable*) skb->dst; + rt = skb->rtable; if (err == 0 && rt->u.dst.error) err = -rt->u.dst.error; } else { @@ -2726,22 +2754,22 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void }, .oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0, }; - err = ip_route_output_key(&init_net, &rt, &fl); + err = ip_route_output_key(net, &rt, &fl); } if (err) goto errout_free; - skb->dst = &rt->u.dst; + skb->rtable = rt; if (rtm->rtm_flags & RTM_F_NOTIFY) rt->rt_flags |= RTCF_NOTIFY; err = rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, - RTM_NEWROUTE, 0, 0); + RTM_NEWROUTE, 0, 0); if (err <= 0) goto errout_free; - err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid); + err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).pid); errout: return err; @@ -2755,6 +2783,9 @@ int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb) struct rtable *rt; int h, s_h; int idx, s_idx; + struct net *net; + + net = skb->sk->sk_net; s_h = cb->args[0]; if (s_h < 0) @@ -2764,7 +2795,7 @@ int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb) rcu_read_lock_bh(); for (rt = rcu_dereference(rt_hash_table[h].chain), idx = 0; rt; rt = rcu_dereference(rt->u.dst.rt_next), idx++) { - if (idx < s_idx) + if (rt->u.dst.dev->nd_net != net || idx < s_idx) continue; if (rt->rt_genid != atomic_read(&rt_genid)) continue; @@ -3040,7 +3071,7 @@ int __init ip_rt_init(void) ip_rt_secret_interval; add_timer(&rt_secret_timer); - if (ip_rt_proc_init(&init_net)) + if (ip_rt_proc_init()) printk(KERN_ERR "Unable to create route proc files\n"); #ifdef CONFIG_XFRM xfrm_init(); diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index f470fe4511d..4704f27f6c0 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -10,8 +10,6 @@ * 2 of the License, or (at your option) any later version. * * $Id: syncookies.c,v 1.18 2002/02/01 22:01:04 davem Exp $ - * - * Missing: IPv6 support. */ #include <linux/tcp.h> @@ -23,22 +21,25 @@ extern int sysctl_tcp_syncookies; -static __u32 syncookie_secret[2][16-3+SHA_DIGEST_WORDS]; +__u32 syncookie_secret[2][16-3+SHA_DIGEST_WORDS]; +EXPORT_SYMBOL(syncookie_secret); static __init int init_syncookies(void) { get_random_bytes(syncookie_secret, sizeof(syncookie_secret)); return 0; } -module_init(init_syncookies); +__initcall(init_syncookies); #define COOKIEBITS 24 /* Upper bits store count */ #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1) +static DEFINE_PER_CPU(__u32, cookie_scratch)[16 + 5 + SHA_WORKSPACE_WORDS]; + static u32 cookie_hash(__be32 saddr, __be32 daddr, __be16 sport, __be16 dport, u32 count, int c) { - __u32 tmp[16 + 5 + SHA_WORKSPACE_WORDS]; + __u32 *tmp = __get_cpu_var(cookie_scratch); memcpy(tmp + 3, syncookie_secret[c], sizeof(syncookie_secret[c])); tmp[0] = (__force u32)saddr; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 071e83a894a..e0fbc25ca81 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2105,15 +2105,12 @@ static int do_tcp_setsockopt(struct sock *sk, int level, break; case TCP_DEFER_ACCEPT: - icsk->icsk_accept_queue.rskq_defer_accept = 0; - if (val > 0) { - /* Translate value in seconds to number of - * retransmits */ - while (icsk->icsk_accept_queue.rskq_defer_accept < 32 && - val > ((TCP_TIMEOUT_INIT / HZ) << - icsk->icsk_accept_queue.rskq_defer_accept)) - icsk->icsk_accept_queue.rskq_defer_accept++; - icsk->icsk_accept_queue.rskq_defer_accept++; + if (val < 0) { + err = -EINVAL; + } else { + if (val > MAX_TCP_ACCEPT_DEFERRED) + val = MAX_TCP_ACCEPT_DEFERRED; + icsk->icsk_accept_queue.rskq_defer_accept = val; } break; @@ -2295,8 +2292,7 @@ static int do_tcp_getsockopt(struct sock *sk, int level, val = (val ? : sysctl_tcp_fin_timeout) / HZ; break; case TCP_DEFER_ACCEPT: - val = !icsk->icsk_accept_queue.rskq_defer_accept ? 0 : - ((TCP_TIMEOUT_INIT / HZ) << (icsk->icsk_accept_queue.rskq_defer_accept - 1)); + val = icsk->icsk_accept_queue.rskq_defer_accept; break; case TCP_WINDOW_CLAMP: val = tp->window_clamp; diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c index 3aa0b23c1ea..eb5b9854c8c 100644 --- a/net/ipv4/tcp_cubic.c +++ b/net/ipv4/tcp_cubic.c @@ -1,12 +1,13 @@ /* - * TCP CUBIC: Binary Increase Congestion control for TCP v2.1 - * + * TCP CUBIC: Binary Increase Congestion control for TCP v2.2 + * Home page: + * http://netsrv.csc.ncsu.edu/twiki/bin/view/Main/BIC * This is from the implementation of CUBIC TCP in * Injong Rhee, Lisong Xu. * "CUBIC: A New TCP-Friendly High-Speed TCP Variant * in PFLDnet 2005 * Available from: - * http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/cubic-paper.pdf + * http://netsrv.csc.ncsu.edu/export/cubic-paper.pdf * * Unless CUBIC is enabled and congestion window is large * this behaves the same as the original Reno. @@ -20,15 +21,10 @@ #define BICTCP_BETA_SCALE 1024 /* Scale factor beta calculation * max_cwnd = snd_cwnd * beta */ -#define BICTCP_B 4 /* - * In binary search, - * go to point (max+min)/N - */ #define BICTCP_HZ 10 /* BIC HZ 2^10 = 1024 */ static int fast_convergence __read_mostly = 1; -static int max_increment __read_mostly = 16; -static int beta __read_mostly = 819; /* = 819/1024 (BICTCP_BETA_SCALE) */ +static int beta __read_mostly = 717; /* = 717/1024 (BICTCP_BETA_SCALE) */ static int initial_ssthresh __read_mostly; static int bic_scale __read_mostly = 41; static int tcp_friendliness __read_mostly = 1; @@ -40,9 +36,7 @@ static u64 cube_factor __read_mostly; /* Note parameters that are used for precomputing scale factors are read-only */ module_param(fast_convergence, int, 0644); MODULE_PARM_DESC(fast_convergence, "turn on/off fast convergence"); -module_param(max_increment, int, 0644); -MODULE_PARM_DESC(max_increment, "Limit on increment allowed during binary search"); -module_param(beta, int, 0444); +module_param(beta, int, 0644); MODULE_PARM_DESC(beta, "beta for multiplicative increase"); module_param(initial_ssthresh, int, 0644); MODULE_PARM_DESC(initial_ssthresh, "initial value of slow start threshold"); @@ -145,7 +139,7 @@ static u32 cubic_root(u64 a) static inline void bictcp_update(struct bictcp *ca, u32 cwnd) { u64 offs; - u32 delta, t, bic_target, min_cnt, max_cnt; + u32 delta, t, bic_target, max_cnt; ca->ack_cnt++; /* count the number of ACKs */ @@ -211,19 +205,6 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd) ca->cnt = 100 * cwnd; /* very small increment*/ } - if (ca->delay_min > 0) { - /* max increment = Smax * rtt / 0.1 */ - min_cnt = (cwnd * HZ * 8)/(10 * max_increment * ca->delay_min); - - /* use concave growth when the target is above the origin */ - if (ca->cnt < min_cnt && t >= ca->bic_K) - ca->cnt = min_cnt; - } - - /* slow start and low utilization */ - if (ca->loss_cwnd == 0) /* could be aggressive in slow start */ - ca->cnt = 50; - /* TCP Friendly */ if (tcp_friendliness) { u32 scale = beta_scale; @@ -391,4 +372,4 @@ module_exit(cubictcp_unregister); MODULE_AUTHOR("Sangtae Ha, Stephen Hemminger"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("CUBIC TCP"); -MODULE_VERSION("2.1"); +MODULE_VERSION("2.2"); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 7facdb0f696..6e46b4c0f28 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3561,7 +3561,7 @@ static void tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th) * cases we should never reach this piece of code. */ printk(KERN_ERR "%s: Impossible, sk->sk_state=%d\n", - __FUNCTION__, sk->sk_state); + __func__, sk->sk_state); break; } @@ -4451,6 +4451,49 @@ static void tcp_urg(struct sock *sk, struct sk_buff *skb, struct tcphdr *th) } } +static int tcp_defer_accept_check(struct sock *sk) +{ + struct tcp_sock *tp = tcp_sk(sk); + + if (tp->defer_tcp_accept.request) { + int queued_data = tp->rcv_nxt - tp->copied_seq; + int hasfin = !skb_queue_empty(&sk->sk_receive_queue) ? + tcp_hdr((struct sk_buff *) + sk->sk_receive_queue.prev)->fin : 0; + + if (queued_data && hasfin) + queued_data--; + + if (queued_data && + tp->defer_tcp_accept.listen_sk->sk_state == TCP_LISTEN) { + if (sock_flag(sk, SOCK_KEEPOPEN)) { + inet_csk_reset_keepalive_timer(sk, + keepalive_time_when(tp)); + } else { + inet_csk_delete_keepalive_timer(sk); + } + + inet_csk_reqsk_queue_add( + tp->defer_tcp_accept.listen_sk, + tp->defer_tcp_accept.request, + sk); + + tp->defer_tcp_accept.listen_sk->sk_data_ready( + tp->defer_tcp_accept.listen_sk, 0); + + sock_put(tp->defer_tcp_accept.listen_sk); + sock_put(sk); + tp->defer_tcp_accept.listen_sk = NULL; + tp->defer_tcp_accept.request = NULL; + } else if (hasfin || + tp->defer_tcp_accept.listen_sk->sk_state != TCP_LISTEN) { + tcp_reset(sk); + return -1; + } + } + return 0; +} + static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen) { struct tcp_sock *tp = tcp_sk(sk); @@ -4811,6 +4854,9 @@ step5: tcp_data_snd_check(sk); tcp_ack_snd_check(sk); + + if (tcp_defer_accept_check(sk)) + return -1; return 0; csum_error: @@ -5330,6 +5376,7 @@ discard: EXPORT_SYMBOL(sysctl_tcp_ecn); EXPORT_SYMBOL(sysctl_tcp_reordering); +EXPORT_SYMBOL(sysctl_tcp_adv_win_scale); EXPORT_SYMBOL(tcp_parse_options); EXPORT_SYMBOL(tcp_rcv_established); EXPORT_SYMBOL(tcp_rcv_state_process); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 00156bf421c..1a47719a55a 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -552,7 +552,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) if (th->rst) return; - if (((struct rtable *)skb->dst)->rt_type != RTN_LOCAL) + if (skb->rtable->rt_type != RTN_LOCAL) return; /* Swap the send and the receive. */ @@ -723,8 +723,8 @@ static void tcp_v4_reqsk_send_ack(struct sk_buff *skb, * This still operates on a request_sock only, not on a big * socket. */ -static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req, - struct dst_entry *dst) +static int __tcp_v4_send_synack(struct sock *sk, struct request_sock *req, + struct dst_entry *dst) { const struct inet_request_sock *ireq = inet_rsk(req); int err = -1; @@ -732,7 +732,7 @@ static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req, /* First, grab a route. */ if (!dst && (dst = inet_csk_route_req(sk, req)) == NULL) - goto out; + return -1; skb = tcp_make_synack(sk, dst, req); @@ -751,11 +751,15 @@ static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req, err = net_xmit_eval(err); } -out: dst_release(dst); return err; } +static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req) +{ + return __tcp_v4_send_synack(sk, req, NULL); +} + /* * IPv4 request_sock destructor. */ @@ -1258,8 +1262,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) #endif /* Never answer to SYNs send to broadcast or multicast */ - if (((struct rtable *)skb->dst)->rt_flags & - (RTCF_BROADCAST | RTCF_MULTICAST)) + if (skb->rtable->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) goto drop; /* TW buckets are converted to open requests without @@ -1351,8 +1354,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) (s32)(peer->tcp_ts - req->ts_recent) > TCP_PAWS_WINDOW) { NET_INC_STATS_BH(LINUX_MIB_PAWSPASSIVEREJECTED); - dst_release(dst); - goto drop_and_free; + goto drop_and_release; } } /* Kill the following clause, if you dislike this way. */ @@ -1372,24 +1374,21 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) "request from %u.%u.%u.%u/%u\n", NIPQUAD(saddr), ntohs(tcp_hdr(skb)->source)); - dst_release(dst); - goto drop_and_free; + goto drop_and_release; } isn = tcp_v4_init_sequence(skb); } tcp_rsk(req)->snt_isn = isn; - if (tcp_v4_send_synack(sk, req, dst)) + if (__tcp_v4_send_synack(sk, req, dst) || want_cookie) goto drop_and_free; - if (want_cookie) { - reqsk_free(req); - } else { - inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); - } + inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); return 0; +drop_and_release: + dst_release(dst); drop_and_free: reqsk_free(req); drop: @@ -1921,6 +1920,14 @@ int tcp_v4_destroy_sock(struct sock *sk) sk->sk_sndmsg_page = NULL; } + if (tp->defer_tcp_accept.request) { + reqsk_free(tp->defer_tcp_accept.request); + sock_put(tp->defer_tcp_accept.listen_sk); + sock_put(sk); + tp->defer_tcp_accept.listen_sk = NULL; + tp->defer_tcp_accept.request = NULL; + } + atomic_dec(&tcp_sockets_allocated); return 0; @@ -1949,6 +1956,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur) struct hlist_node *node; struct sock *sk = cur; struct tcp_iter_state* st = seq->private; + struct net *net = st->net; if (!sk) { st->bucket = 0; @@ -1965,7 +1973,8 @@ static void *listening_get_next(struct seq_file *seq, void *cur) req = req->dl_next; while (1) { while (req) { - if (req->rsk_ops->family == st->family) { + if (req->rsk_ops->family == st->family && + req->sk->sk_net == net) { cur = req; goto out; } @@ -1989,7 +1998,7 @@ get_req: } get_sk: sk_for_each_from(sk, node) { - if (sk->sk_family == st->family) { + if (sk->sk_family == st->family && sk->sk_net == net) { cur = sk; goto out; } @@ -2028,6 +2037,7 @@ static void *listening_get_idx(struct seq_file *seq, loff_t *pos) static void *established_get_first(struct seq_file *seq) { struct tcp_iter_state* st = seq->private; + struct net *net = st->net; void *rc = NULL; for (st->bucket = 0; st->bucket < tcp_hashinfo.ehash_size; ++st->bucket) { @@ -2038,7 +2048,8 @@ static void *established_get_first(struct seq_file *seq) read_lock_bh(lock); sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) { - if (sk->sk_family != st->family) { + if (sk->sk_family != st->family || + sk->sk_net != net) { continue; } rc = sk; @@ -2047,7 +2058,8 @@ static void *established_get_first(struct seq_file *seq) st->state = TCP_SEQ_STATE_TIME_WAIT; inet_twsk_for_each(tw, node, &tcp_hashinfo.ehash[st->bucket].twchain) { - if (tw->tw_family != st->family) { + if (tw->tw_family != st->family || + tw->tw_net != net) { continue; } rc = tw; @@ -2066,6 +2078,7 @@ static void *established_get_next(struct seq_file *seq, void *cur) struct inet_timewait_sock *tw; struct hlist_node *node; struct tcp_iter_state* st = seq->private; + struct net *net = st->net; ++st->num; @@ -2073,7 +2086,7 @@ static void *established_get_next(struct seq_file *seq, void *cur) tw = cur; tw = tw_next(tw); get_tw: - while (tw && tw->tw_family != st->family) { + while (tw && (tw->tw_family != st->family || tw->tw_net != net)) { tw = tw_next(tw); } if (tw) { @@ -2094,7 +2107,7 @@ get_tw: sk = sk_next(sk); sk_for_each_from(sk, node) { - if (sk->sk_family == st->family) + if (sk->sk_family == st->family && sk->sk_net == net) goto found; } @@ -2202,6 +2215,7 @@ static int tcp_seq_open(struct inode *inode, struct file *file) struct tcp_seq_afinfo *afinfo = PDE(inode)->data; struct seq_file *seq; struct tcp_iter_state *s; + struct net *net; int rc; if (unlikely(afinfo == NULL)) @@ -2210,25 +2224,44 @@ static int tcp_seq_open(struct inode *inode, struct file *file) s = kzalloc(sizeof(*s), GFP_KERNEL); if (!s) return -ENOMEM; + + rc = -ENXIO; + net = get_proc_net(inode); + if (!net) + goto out_kfree; + s->family = afinfo->family; s->seq_ops.start = tcp_seq_start; s->seq_ops.next = tcp_seq_next; s->seq_ops.show = afinfo->seq_show; s->seq_ops.stop = tcp_seq_stop; + s->net = net; rc = seq_open(file, &s->seq_ops); if (rc) - goto out_kfree; - seq = file->private_data; + goto out_put_net; + seq = file->private_data; seq->private = s; out: return rc; +out_put_net: + put_net(net); out_kfree: kfree(s); goto out; } -int tcp_proc_register(struct tcp_seq_afinfo *afinfo) +static int tcp_seq_release(struct inode *inode, struct file *file) +{ + struct seq_file *seq = file->private_data; + struct tcp_iter_state *s = seq->private; + + put_net(s->net); + seq_release_private(inode, file); + return 0; +} + +int tcp_proc_register(struct net *net, struct tcp_seq_afinfo *afinfo) { int rc = 0; struct proc_dir_entry *p; @@ -2239,9 +2272,9 @@ int tcp_proc_register(struct tcp_seq_afinfo *afinfo) afinfo->seq_fops->open = tcp_seq_open; afinfo->seq_fops->read = seq_read; afinfo->seq_fops->llseek = seq_lseek; - afinfo->seq_fops->release = seq_release_private; + afinfo->seq_fops->release = tcp_seq_release; - p = proc_net_fops_create(&init_net, afinfo->name, S_IRUGO, afinfo->seq_fops); + p = proc_net_fops_create(net, afinfo->name, S_IRUGO, afinfo->seq_fops); if (p) p->data = afinfo; else @@ -2249,11 +2282,11 @@ int tcp_proc_register(struct tcp_seq_afinfo *afinfo) return rc; } -void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo) +void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo) { if (!afinfo) return; - proc_net_remove(&init_net, afinfo->name); + proc_net_remove(net, afinfo->name); memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops)); } @@ -2394,12 +2427,12 @@ static struct tcp_seq_afinfo tcp4_seq_afinfo = { int __init tcp4_proc_init(void) { - return tcp_proc_register(&tcp4_seq_afinfo); + return tcp_proc_register(&init_net, &tcp4_seq_afinfo); } void tcp4_proc_exit(void) { - tcp_proc_unregister(&tcp4_seq_afinfo); + tcp_proc_unregister(&init_net, &tcp4_seq_afinfo); } #endif /* CONFIG_PROC_FS */ @@ -2435,7 +2468,7 @@ struct proto tcp_prot = { .obj_size = sizeof(struct tcp_sock), .twsk_prot = &tcp_timewait_sock_ops, .rsk_prot = &tcp_request_sock_ops, - .hashinfo = &tcp_hashinfo, + .h.hashinfo = &tcp_hashinfo, #ifdef CONFIG_COMPAT .compat_setsockopt = compat_tcp_setsockopt, .compat_getsockopt = compat_tcp_getsockopt, @@ -2443,7 +2476,7 @@ struct proto tcp_prot = { REF_PROTO_INUSE(tcp) }; -void __init tcp_v4_init(struct net_proto_family *ops) +void __init tcp_v4_init(void) { if (inet_csk_ctl_sock_create(&tcp_socket, PF_INET, SOCK_RAW, IPPROTO_TCP) < 0) diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index b61b76847ad..019c8c16e5c 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -35,6 +35,8 @@ #endif int sysctl_tcp_syncookies __read_mostly = SYNC_INIT; +EXPORT_SYMBOL(sysctl_tcp_syncookies); + int sysctl_tcp_abort_on_overflow __read_mostly; struct inet_timewait_death_row tcp_death_row = { @@ -536,7 +538,7 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb, * Enforce "SYN-ACK" according to figure 8, figure 6 * of RFC793, fixed by RFC1122. */ - req->rsk_ops->rtx_syn_ack(sk, req, NULL); + req->rsk_ops->rtx_syn_ack(sk, req); return NULL; } @@ -569,10 +571,8 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb, does sequence test, SYN is truncated, and thus we consider it a bare ACK. - If icsk->icsk_accept_queue.rskq_defer_accept, we silently drop this - bare ACK. Otherwise, we create an established connection. Both - ends (listening sockets) accept the new incoming connection and try - to talk to each other. 8-) + Both ends (listening sockets) accept the new incoming + connection and try to talk to each other. 8-) Note: This case is both harmless, and rare. Possibility is about the same as us discovering intelligent life on another plant tomorrow. @@ -640,13 +640,6 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb, if (!(flg & TCP_FLAG_ACK)) return NULL; - /* If TCP_DEFER_ACCEPT is set, drop bare ACK. */ - if (inet_csk(sk)->icsk_accept_queue.rskq_defer_accept && - TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) { - inet_rsk(req)->acked = 1; - return NULL; - } - /* OK, ACK is valid, create big socket and * feed this segment to it. It will repeat all * the tests. THIS SEGMENT MUST MOVE SOCKET TO @@ -685,7 +678,24 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb, inet_csk_reqsk_queue_unlink(sk, req, prev); inet_csk_reqsk_queue_removed(sk, req); - inet_csk_reqsk_queue_add(sk, req, child); + if (inet_csk(sk)->icsk_accept_queue.rskq_defer_accept && + TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) { + + /* the accept queue handling is done is est recv slow + * path so lets make sure to start there + */ + tcp_sk(child)->pred_flags = 0; + sock_hold(sk); + sock_hold(child); + tcp_sk(child)->defer_tcp_accept.listen_sk = sk; + tcp_sk(child)->defer_tcp_accept.request = req; + + inet_csk_reset_keepalive_timer(child, + inet_csk(sk)->icsk_accept_queue.rskq_defer_accept * HZ); + } else { + inet_csk_reqsk_queue_add(sk, req, child); + } + return child; listen_overflow: diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 01578f544ad..a627616314b 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -255,7 +255,7 @@ static u16 tcp_select_window(struct sock *sk) * * Relax Will Robinson. */ - new_win = cur_win; + new_win = ALIGN(cur_win, 1 << tp->rx_opt.rcv_wscale); } tp->rcv_wnd = new_win; tp->rcv_wup = tp->rcv_nxt; @@ -998,7 +998,7 @@ unsigned int tcp_current_mss(struct sock *sk, int large_allowed) xmit_size_goal = mss_now; if (doing_tso) { - xmit_size_goal = (65535 - + xmit_size_goal = ((sk->sk_gso_max_size - 1) - inet_csk(sk)->icsk_af_ops->net_header_len - inet_csk(sk)->icsk_ext_hdr_len - tp->tcp_header_len); @@ -1282,7 +1282,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb) limit = min(send_win, cong_win); /* If a full-sized TSO skb can be sent, do it. */ - if (limit >= 65536) + if (limit >= sk->sk_gso_max_size) goto send_now; if (sysctl_tcp_tso_win_divisor) { @@ -2568,6 +2568,7 @@ void tcp_send_probe0(struct sock *sk) } } +EXPORT_SYMBOL(tcp_select_initial_window); EXPORT_SYMBOL(tcp_connect); EXPORT_SYMBOL(tcp_make_synack); EXPORT_SYMBOL(tcp_simple_retransmit); diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 803d758a2b1..160d16f9f4f 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -481,6 +481,11 @@ static void tcp_keepalive_timer (unsigned long data) goto death; } + if (tp->defer_tcp_accept.request && sk->sk_state == TCP_ESTABLISHED) { + tcp_send_active_reset(sk, GFP_ATOMIC); + goto death; + } + if (!sock_flag(sk, SOCK_KEEPOPEN) || sk->sk_state == TCP_CLOSE) goto out; diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 7ea1b67b6de..8c1f5eaafcd 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -143,18 +143,17 @@ static inline int __udp_lib_lport_inuse(struct net *net, __u16 num, } /** - * __udp_lib_get_port - UDP/-Lite port lookup for IPv4 and IPv6 + * udp_lib_get_port - UDP/-Lite port lookup for IPv4 and IPv6 * * @sk: socket struct in question * @snum: port number to look up - * @udptable: hash list table, must be of UDP_HTABLE_SIZE * @saddr_comp: AF-dependent comparison of bound local IP addresses */ -int __udp_lib_get_port(struct sock *sk, unsigned short snum, - struct hlist_head udptable[], +int udp_lib_get_port(struct sock *sk, unsigned short snum, int (*saddr_comp)(const struct sock *sk1, const struct sock *sk2 ) ) { + struct hlist_head *udptable = sk->sk_prot->h.udp_hash; struct hlist_node *node; struct hlist_head *head; struct sock *sk2; @@ -240,13 +239,7 @@ fail: return error; } -int udp_get_port(struct sock *sk, unsigned short snum, - int (*scmp)(const struct sock *, const struct sock *)) -{ - return __udp_lib_get_port(sk, snum, udp_hash, scmp); -} - -int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) +static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) { struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2); @@ -255,9 +248,9 @@ int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) inet1->rcv_saddr == inet2->rcv_saddr )); } -static inline int udp_v4_get_port(struct sock *sk, unsigned short snum) +int udp_v4_get_port(struct sock *sk, unsigned short snum) { - return udp_get_port(sk, snum, ipv4_rcv_saddr_equal); + return udp_lib_get_port(sk, snum, ipv4_rcv_saddr_equal); } /* UDP is nearly always wildcards out the wazoo, it makes no sense to try @@ -1498,6 +1491,7 @@ struct proto udp_prot = { .sysctl_wmem = &sysctl_udp_wmem_min, .sysctl_rmem = &sysctl_udp_rmem_min, .obj_size = sizeof(struct udp_sock), + .h.udp_hash = udp_hash, #ifdef CONFIG_COMPAT .compat_setsockopt = compat_udp_setsockopt, .compat_getsockopt = compat_udp_getsockopt, @@ -1512,10 +1506,13 @@ static struct sock *udp_get_first(struct seq_file *seq) { struct sock *sk; struct udp_iter_state *state = seq->private; + struct net *net = state->net; for (state->bucket = 0; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) { struct hlist_node *node; sk_for_each(sk, node, state->hashtable + state->bucket) { + if (sk->sk_net != net) + continue; if (sk->sk_family == state->family) goto found; } @@ -1528,12 +1525,13 @@ found: static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk) { struct udp_iter_state *state = seq->private; + struct net *net = state->net; do { sk = sk_next(sk); try_again: ; - } while (sk && sk->sk_family != state->family); + } while (sk && (sk->sk_net != net || sk->sk_family != state->family)); if (!sk && ++state->bucket < UDP_HTABLE_SIZE) { sk = sk_head(state->hashtable + state->bucket); @@ -1582,33 +1580,53 @@ static int udp_seq_open(struct inode *inode, struct file *file) { struct udp_seq_afinfo *afinfo = PDE(inode)->data; struct seq_file *seq; + struct net *net; int rc = -ENOMEM; struct udp_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL); if (!s) goto out; + + rc = -ENXIO; + net = get_proc_net(inode); + if (!net) + goto out_kfree; + s->family = afinfo->family; s->hashtable = afinfo->hashtable; s->seq_ops.start = udp_seq_start; s->seq_ops.next = udp_seq_next; s->seq_ops.show = afinfo->seq_show; s->seq_ops.stop = udp_seq_stop; + s->net = net; rc = seq_open(file, &s->seq_ops); if (rc) - goto out_kfree; + goto out_put_net; - seq = file->private_data; + seq = file->private_data; seq->private = s; out: return rc; +out_put_net: + put_net(net); out_kfree: kfree(s); goto out; } +static int udp_seq_release(struct inode *inode, struct file *file) +{ + struct seq_file *seq = file->private_data; + struct udp_iter_state *s = seq->private; + + put_net(s->net); + seq_release_private(inode, file); + return 0; +} + /* ------------------------------------------------------------------------ */ -int udp_proc_register(struct udp_seq_afinfo *afinfo) +int udp_proc_register(struct net *net, struct udp_seq_afinfo *afinfo) { struct proc_dir_entry *p; int rc = 0; @@ -1619,9 +1637,9 @@ int udp_proc_register(struct udp_seq_afinfo *afinfo) afinfo->seq_fops->open = udp_seq_open; afinfo->seq_fops->read = seq_read; afinfo->seq_fops->llseek = seq_lseek; - afinfo->seq_fops->release = seq_release_private; + afinfo->seq_fops->release = udp_seq_release; - p = proc_net_fops_create(&init_net, afinfo->name, S_IRUGO, afinfo->seq_fops); + p = proc_net_fops_create(net, afinfo->name, S_IRUGO, afinfo->seq_fops); if (p) p->data = afinfo; else @@ -1629,11 +1647,11 @@ int udp_proc_register(struct udp_seq_afinfo *afinfo) return rc; } -void udp_proc_unregister(struct udp_seq_afinfo *afinfo) +void udp_proc_unregister(struct net *net, struct udp_seq_afinfo *afinfo) { if (!afinfo) return; - proc_net_remove(&init_net, afinfo->name); + proc_net_remove(net, afinfo->name); memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops)); } @@ -1685,12 +1703,12 @@ static struct udp_seq_afinfo udp4_seq_afinfo = { int __init udp4_proc_init(void) { - return udp_proc_register(&udp4_seq_afinfo); + return udp_proc_register(&init_net, &udp4_seq_afinfo); } void udp4_proc_exit(void) { - udp_proc_unregister(&udp4_seq_afinfo); + udp_proc_unregister(&init_net, &udp4_seq_afinfo); } #endif /* CONFIG_PROC_FS */ @@ -1717,12 +1735,12 @@ EXPORT_SYMBOL(udp_disconnect); EXPORT_SYMBOL(udp_hash); EXPORT_SYMBOL(udp_hash_lock); EXPORT_SYMBOL(udp_ioctl); -EXPORT_SYMBOL(udp_get_port); EXPORT_SYMBOL(udp_prot); EXPORT_SYMBOL(udp_sendmsg); EXPORT_SYMBOL(udp_lib_getsockopt); EXPORT_SYMBOL(udp_lib_setsockopt); EXPORT_SYMBOL(udp_poll); +EXPORT_SYMBOL(udp_lib_get_port); #ifdef CONFIG_PROC_FS EXPORT_SYMBOL(udp_proc_register); diff --git a/net/ipv4/udp_impl.h b/net/ipv4/udp_impl.h index 6c55828e41b..7288bf7977f 100644 --- a/net/ipv4/udp_impl.h +++ b/net/ipv4/udp_impl.h @@ -8,11 +8,7 @@ extern int __udp4_lib_rcv(struct sk_buff *, struct hlist_head [], int ); extern void __udp4_lib_err(struct sk_buff *, u32, struct hlist_head []); -extern int __udp_lib_get_port(struct sock *sk, unsigned short snum, - struct hlist_head udptable[], - int (*)(const struct sock*,const struct sock*)); -extern int ipv4_rcv_saddr_equal(const struct sock *, const struct sock *); - +extern int udp_v4_get_port(struct sock *sk, unsigned short snum); extern int udp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen); diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c index 001b881ca36..8d42e344b04 100644 --- a/net/ipv4/udplite.c +++ b/net/ipv4/udplite.c @@ -17,17 +17,6 @@ DEFINE_SNMP_STAT(struct udp_mib, udplite_statistics) __read_mostly; struct hlist_head udplite_hash[UDP_HTABLE_SIZE]; -int udplite_get_port(struct sock *sk, unsigned short p, - int (*c)(const struct sock *, const struct sock *)) -{ - return __udp_lib_get_port(sk, p, udplite_hash, c); -} - -static int udplite_v4_get_port(struct sock *sk, unsigned short snum) -{ - return udplite_get_port(sk, snum, ipv4_rcv_saddr_equal); -} - static int udplite_rcv(struct sk_buff *skb) { return __udp4_lib_rcv(skb, udplite_hash, IPPROTO_UDPLITE); @@ -63,8 +52,9 @@ struct proto udplite_prot = { .backlog_rcv = udp_queue_rcv_skb, .hash = udp_lib_hash, .unhash = udp_lib_unhash, - .get_port = udplite_v4_get_port, + .get_port = udp_v4_get_port, .obj_size = sizeof(struct udp_sock), + .h.udp_hash = udplite_hash, #ifdef CONFIG_COMPAT .compat_setsockopt = compat_udp_setsockopt, .compat_getsockopt = compat_udp_getsockopt, @@ -105,17 +95,16 @@ void __init udplite4_register(void) inet_register_protosw(&udplite4_protosw); #ifdef CONFIG_PROC_FS - if (udp_proc_register(&udplite4_seq_afinfo)) /* udplite4_proc_init() */ - printk(KERN_ERR "%s: Cannot register /proc!\n", __FUNCTION__); + if (udp_proc_register(&init_net, &udplite4_seq_afinfo)) + printk(KERN_ERR "%s: Cannot register /proc!\n", __func__); #endif return; out_unregister_proto: proto_unregister(&udplite_prot); out_register_err: - printk(KERN_CRIT "%s: Cannot add UDP-Lite protocol.\n", __FUNCTION__); + printk(KERN_CRIT "%s: Cannot add UDP-Lite protocol.\n", __func__); } EXPORT_SYMBOL(udplite_hash); EXPORT_SYMBOL(udplite_prot); -EXPORT_SYMBOL(udplite_get_port); |