From 8030f54499925d073a88c09f30d5d844fb1b3190 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 22 Feb 2007 01:53:47 +0900 Subject: [IPV4] devinet: Register inetdev earlier. This patch allocates inetdev at registration for all devices in line with IPv6. This allows sysctl configuration on the devices to occur before they're brought up or addresses are added. Signed-off-by: Herbert Xu Signed-off-by: YOSHIFUJI Hideaki --- net/ipv4/devinet.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'net/ipv4/devinet.c') diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 8a0ec10a13a7..e10794dc5f64 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1054,12 +1054,14 @@ static int inetdev_event(struct notifier_block *this, unsigned long event, ASSERT_RTNL(); if (!in_dev) { - if (event == NETDEV_REGISTER && dev == &loopback_dev) { + if (event == NETDEV_REGISTER) { in_dev = inetdev_init(dev); if (!in_dev) panic("devinet: Failed to create loopback\n"); - in_dev->cnf.no_xfrm = 1; - in_dev->cnf.no_policy = 1; + if (dev == &loopback_dev) { + in_dev->cnf.no_xfrm = 1; + in_dev->cnf.no_policy = 1; + } } goto out; } -- cgit v1.2.3 From c4e38f41e34ad853651d66227aae23e48457dce0 Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Fri, 9 Mar 2007 13:43:24 -0800 Subject: [IPV4]: Fix rtm_to_ifaddr() error handling. Return negative error value (embedded in the pointer) instead of returning NULL. Signed-off-by: Evgeniy Polyakov Signed-off-by: David S. Miller --- net/ipv4/devinet.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'net/ipv4/devinet.c') diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index e10794dc5f64..98a00d0edc76 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -502,8 +502,10 @@ static struct in_ifaddr *rtm_to_ifaddr(struct nlmsghdr *nlh) goto errout; ifm = nlmsg_data(nlh); - if (ifm->ifa_prefixlen > 32 || tb[IFA_LOCAL] == NULL) + if (ifm->ifa_prefixlen > 32 || tb[IFA_LOCAL] == NULL) { + err = -EINVAL; goto errout; + } dev = __dev_get_by_index(ifm->ifa_index); if (dev == NULL) { -- cgit v1.2.3 From 132adf54639cf7dd9315e8df89c2faa59f6e46d9 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 8 Mar 2007 20:44:43 -0800 Subject: [IPV4]: cleanup Add whitespace around keywords. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/ipv4/af_inet.c | 2 +- net/ipv4/arp.c | 2 +- net/ipv4/cipso_ipv4.c | 2 +- net/ipv4/devinet.c | 4 +- net/ipv4/fib_trie.c | 17 +- net/ipv4/ip_fragment.c | 26 +- net/ipv4/ip_output.c | 2 +- net/ipv4/ip_sockglue.c | 1127 +++++++++++++++++++++--------------------- net/ipv4/ipconfig.c | 4 +- net/ipv4/ipmr.c | 305 ++++++------ net/ipv4/xfrm4_mode_tunnel.c | 2 +- net/ipv4/xfrm4_policy.c | 2 +- 12 files changed, 745 insertions(+), 750 deletions(-) (limited to 'net/ipv4/devinet.c') diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index df41856fc603..6e5575b0abef 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1339,7 +1339,7 @@ static int __init inet_init(void) * Initialise per-cpu ipv4 mibs */ - if(init_ipv4_mibs()) + if (init_ipv4_mibs()) printk(KERN_CRIT "inet_init: Cannot init ipv4 mibs\n"); ; ipv4_proc_init(); diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 1a3488a83f49..e6e196cd3b8c 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -1178,7 +1178,7 @@ int arp_ioctl(unsigned int cmd, void __user *arg) goto out; } - switch(cmd) { + switch (cmd) { case SIOCDARP: err = arp_req_delete(&r, dev); break; diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 2ce5b693a8bd..b0182aa2c81a 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -1174,7 +1174,7 @@ static int cipso_v4_map_cat_rng_ntoh(const struct cipso_v4_doi *doi_def, u16 cat_low; u16 cat_high; - for(net_iter = 0; net_iter < net_cat_len; net_iter += 4) { + for (net_iter = 0; net_iter < net_cat_len; net_iter += 4) { cat_high = ntohs(*((__be16 *)&net_cat[net_iter])); if ((net_iter + 4) <= net_cat_len) cat_low = ntohs(*((__be16 *)&net_cat[net_iter + 2])); diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 98a00d0edc76..043857bd151c 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -633,7 +633,7 @@ int devinet_ioctl(unsigned int cmd, void __user *arg) dev_load(ifr.ifr_name); #endif - switch(cmd) { + switch (cmd) { case SIOCGIFADDR: /* Get interface address */ case SIOCGIFBRDADDR: /* Get the broadcast address */ case SIOCGIFDSTADDR: /* Get the destination address */ @@ -708,7 +708,7 @@ int devinet_ioctl(unsigned int cmd, void __user *arg) if (!ifa && cmd != SIOCSIFADDR && cmd != SIOCSIFFLAGS) goto done; - switch(cmd) { + switch (cmd) { case SIOCGIFADDR: /* Get interface address */ sin->sin_addr.s_addr = ifa->ifa_local; goto rarok; diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 214c34732e84..c331c433acf2 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -350,11 +350,10 @@ static void __tnode_free_rcu(struct rcu_head *head) static inline void tnode_free(struct tnode *tn) { - if(IS_LEAF(tn)) { + if (IS_LEAF(tn)) { struct leaf *l = (struct leaf *) tn; call_rcu_bh(&l->rcu, __leaf_free_rcu); - } - else + } else call_rcu(&tn->rcu, __tnode_free_rcu); } @@ -553,7 +552,7 @@ static struct node *resize(struct trie *t, struct tnode *tn) /* Keep root node larger */ - if(!tn->parent) + if (!tn->parent) inflate_threshold_use = inflate_threshold_root; else inflate_threshold_use = inflate_threshold; @@ -584,7 +583,7 @@ static struct node *resize(struct trie *t, struct tnode *tn) /* Keep root node larger */ - if(!tn->parent) + if (!tn->parent) halve_threshold_use = halve_threshold_root; else halve_threshold_use = halve_threshold; @@ -2039,12 +2038,12 @@ static struct node *fib_trie_get_first(struct fib_trie_iter *iter, { struct node *n ; - if(!t) + if (!t) return NULL; n = rcu_dereference(t->trie); - if(!iter) + if (!iter) return NULL; if (n) { @@ -2084,7 +2083,7 @@ static void trie_collect_stats(struct trie *t, struct trie_stat *s) int i; s->tnodes++; - if(tn->bits < MAX_STAT_DEPTH) + if (tn->bits < MAX_STAT_DEPTH) s->nodesizes[tn->bits]++; for (i = 0; i < (1<bits); i++) @@ -2250,7 +2249,7 @@ static inline const char *rtn_scope(enum rt_scope_t s) { static char buf[32]; - switch(s) { + switch (s) { case RT_SCOPE_UNIVERSE: return "universe"; case RT_SCOPE_SITE: return "site"; case RT_SCOPE_LINK: return "link"; diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index e10be7d7752d..3dfd7581cfc6 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -184,7 +184,7 @@ static __inline__ struct ipq *frag_alloc_queue(void) { struct ipq *qp = kmalloc(sizeof(struct ipq), GFP_ATOMIC); - if(!qp) + if (!qp) return NULL; atomic_add(sizeof(struct ipq), &ip_frag_mem); return qp; @@ -321,11 +321,11 @@ static struct ipq *ip_frag_intern(struct ipq *qp_in) * promoted read lock to write lock. */ hlist_for_each_entry(qp, n, &ipq_hash[hash], list) { - if(qp->id == qp_in->id && - qp->saddr == qp_in->saddr && - qp->daddr == qp_in->daddr && - qp->protocol == qp_in->protocol && - qp->user == qp_in->user) { + if (qp->id == qp_in->id && + qp->saddr == qp_in->saddr && + qp->daddr == qp_in->daddr && + qp->protocol == qp_in->protocol && + qp->user == qp_in->user) { atomic_inc(&qp->refcnt); write_unlock(&ipfrag_lock); qp_in->last_in |= COMPLETE; @@ -398,11 +398,11 @@ static inline struct ipq *ip_find(struct iphdr *iph, u32 user) read_lock(&ipfrag_lock); hash = ipqhashfn(id, saddr, daddr, protocol); hlist_for_each_entry(qp, n, &ipq_hash[hash], list) { - if(qp->id == id && - qp->saddr == saddr && - qp->daddr == daddr && - qp->protocol == protocol && - qp->user == user) { + if (qp->id == id && + qp->saddr == saddr && + qp->daddr == daddr && + qp->protocol == protocol && + qp->user == user) { atomic_inc(&qp->refcnt); read_unlock(&ipfrag_lock); return qp; @@ -524,7 +524,7 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb) * this fragment, right? */ prev = NULL; - for(next = qp->fragments; next != NULL; next = next->next) { + for (next = qp->fragments; next != NULL; next = next->next) { if (FRAG_CB(next)->offset >= offset) break; /* bingo! */ prev = next; @@ -627,7 +627,7 @@ static struct sk_buff *ip_frag_reasm(struct ipq *qp, struct net_device *dev) ihlen = head->nh.iph->ihl*4; len = ihlen + qp->len; - if(len > 65535) + if (len > 65535) goto out_oversize; /* Head of list must not be cloned. */ diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index d096332f6c6d..5db301b33372 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -566,7 +566,7 @@ slow_path: * Keep copying data until we run out. */ - while(left > 0) { + while (left > 0) { len = left; /* IF: it doesn't fit, use 'mtu' - the data space left */ if (len > mtu) diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 23048d9f3584..c5e41644c80d 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -403,20 +403,20 @@ out: */ static int do_ip_setsockopt(struct sock *sk, int level, - int optname, char __user *optval, int optlen) + int optname, char __user *optval, int optlen) { struct inet_sock *inet = inet_sk(sk); int val=0,err; if (((1<= sizeof(int)) { if (get_user(val, (int __user *) optval)) return -EFAULT; @@ -440,444 +440,444 @@ static int do_ip_setsockopt(struct sock *sk, int level, lock_sock(sk); switch (optname) { - case IP_OPTIONS: - { - struct ip_options * opt = NULL; - if (optlen > 40 || optlen < 0) - goto e_inval; - err = ip_options_get_from_user(&opt, optval, optlen); - if (err) - break; - if (inet->is_icsk) { - struct inet_connection_sock *icsk = inet_csk(sk); + case IP_OPTIONS: + { + struct ip_options * opt = NULL; + if (optlen > 40 || optlen < 0) + goto e_inval; + err = ip_options_get_from_user(&opt, optval, optlen); + if (err) + break; + if (inet->is_icsk) { + struct inet_connection_sock *icsk = inet_csk(sk); #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) - if (sk->sk_family == PF_INET || - (!((1 << sk->sk_state) & - (TCPF_LISTEN | TCPF_CLOSE)) && - inet->daddr != LOOPBACK4_IPV6)) { + if (sk->sk_family == PF_INET || + (!((1 << sk->sk_state) & + (TCPF_LISTEN | TCPF_CLOSE)) && + inet->daddr != LOOPBACK4_IPV6)) { #endif - if (inet->opt) - icsk->icsk_ext_hdr_len -= inet->opt->optlen; - if (opt) - icsk->icsk_ext_hdr_len += opt->optlen; - icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); + if (inet->opt) + icsk->icsk_ext_hdr_len -= inet->opt->optlen; + if (opt) + icsk->icsk_ext_hdr_len += opt->optlen; + icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) - } -#endif } - opt = xchg(&inet->opt, opt); - kfree(opt); - break; +#endif } - case IP_PKTINFO: - if (val) - inet->cmsg_flags |= IP_CMSG_PKTINFO; - else - inet->cmsg_flags &= ~IP_CMSG_PKTINFO; - break; - case IP_RECVTTL: - if (val) - inet->cmsg_flags |= IP_CMSG_TTL; - else - inet->cmsg_flags &= ~IP_CMSG_TTL; - break; - case IP_RECVTOS: - if (val) - inet->cmsg_flags |= IP_CMSG_TOS; - else - inet->cmsg_flags &= ~IP_CMSG_TOS; - break; - case IP_RECVOPTS: - if (val) - inet->cmsg_flags |= IP_CMSG_RECVOPTS; - else - inet->cmsg_flags &= ~IP_CMSG_RECVOPTS; - break; - case IP_RETOPTS: - if (val) - inet->cmsg_flags |= IP_CMSG_RETOPTS; - else - inet->cmsg_flags &= ~IP_CMSG_RETOPTS; + opt = xchg(&inet->opt, opt); + kfree(opt); + break; + } + case IP_PKTINFO: + if (val) + inet->cmsg_flags |= IP_CMSG_PKTINFO; + else + inet->cmsg_flags &= ~IP_CMSG_PKTINFO; + break; + case IP_RECVTTL: + if (val) + inet->cmsg_flags |= IP_CMSG_TTL; + else + inet->cmsg_flags &= ~IP_CMSG_TTL; + break; + case IP_RECVTOS: + if (val) + inet->cmsg_flags |= IP_CMSG_TOS; + else + inet->cmsg_flags &= ~IP_CMSG_TOS; + break; + case IP_RECVOPTS: + if (val) + inet->cmsg_flags |= IP_CMSG_RECVOPTS; + else + inet->cmsg_flags &= ~IP_CMSG_RECVOPTS; + break; + case IP_RETOPTS: + if (val) + inet->cmsg_flags |= IP_CMSG_RETOPTS; + else + inet->cmsg_flags &= ~IP_CMSG_RETOPTS; + break; + case IP_PASSSEC: + if (val) + inet->cmsg_flags |= IP_CMSG_PASSSEC; + else + inet->cmsg_flags &= ~IP_CMSG_PASSSEC; + break; + case IP_TOS: /* This sets both TOS and Precedence */ + if (sk->sk_type == SOCK_STREAM) { + val &= ~3; + val |= inet->tos & 3; + } + if (IPTOS_PREC(val) >= IPTOS_PREC_CRITIC_ECP && + !capable(CAP_NET_ADMIN)) { + err = -EPERM; break; - case IP_PASSSEC: - if (val) - inet->cmsg_flags |= IP_CMSG_PASSSEC; - else - inet->cmsg_flags &= ~IP_CMSG_PASSSEC; + } + if (inet->tos != val) { + inet->tos = val; + sk->sk_priority = rt_tos2priority(val); + sk_dst_reset(sk); + } + break; + case IP_TTL: + if (optlen<1) + goto e_inval; + if (val != -1 && (val < 1 || val>255)) + goto e_inval; + inet->uc_ttl = val; + break; + case IP_HDRINCL: + if (sk->sk_type != SOCK_RAW) { + err = -ENOPROTOOPT; break; - case IP_TOS: /* This sets both TOS and Precedence */ - if (sk->sk_type == SOCK_STREAM) { - val &= ~3; - val |= inet->tos & 3; - } - if (IPTOS_PREC(val) >= IPTOS_PREC_CRITIC_ECP && - !capable(CAP_NET_ADMIN)) { - err = -EPERM; + } + inet->hdrincl = val ? 1 : 0; + break; + case IP_MTU_DISCOVER: + if (val<0 || val>2) + goto e_inval; + inet->pmtudisc = val; + break; + case IP_RECVERR: + inet->recverr = !!val; + if (!val) + skb_queue_purge(&sk->sk_error_queue); + break; + case IP_MULTICAST_TTL: + if (sk->sk_type == SOCK_STREAM) + goto e_inval; + if (optlen<1) + goto e_inval; + if (val==-1) + val = 1; + if (val < 0 || val > 255) + goto e_inval; + inet->mc_ttl = val; + break; + case IP_MULTICAST_LOOP: + if (optlen<1) + goto e_inval; + inet->mc_loop = !!val; + break; + case IP_MULTICAST_IF: + { + struct ip_mreqn mreq; + struct net_device *dev = NULL; + + if (sk->sk_type == SOCK_STREAM) + goto e_inval; + /* + * Check the arguments are allowable + */ + + err = -EFAULT; + if (optlen >= sizeof(struct ip_mreqn)) { + if (copy_from_user(&mreq,optval,sizeof(mreq))) break; - } - if (inet->tos != val) { - inet->tos = val; - sk->sk_priority = rt_tos2priority(val); - sk_dst_reset(sk); - } - break; - case IP_TTL: - if (optlen<1) - goto e_inval; - if (val != -1 && (val < 1 || val>255)) - goto e_inval; - inet->uc_ttl = val; - break; - case IP_HDRINCL: - if (sk->sk_type != SOCK_RAW) { - err = -ENOPROTOOPT; + } else { + memset(&mreq, 0, sizeof(mreq)); + if (optlen >= sizeof(struct in_addr) && + copy_from_user(&mreq.imr_address,optval,sizeof(struct in_addr))) + break; + } + + if (!mreq.imr_ifindex) { + if (mreq.imr_address.s_addr == INADDR_ANY) { + inet->mc_index = 0; + inet->mc_addr = 0; + err = 0; break; } - inet->hdrincl = val ? 1 : 0; - break; - case IP_MTU_DISCOVER: - if (val<0 || val>2) - goto e_inval; - inet->pmtudisc = val; - break; - case IP_RECVERR: - inet->recverr = !!val; - if (!val) - skb_queue_purge(&sk->sk_error_queue); - break; - case IP_MULTICAST_TTL: - if (sk->sk_type == SOCK_STREAM) - goto e_inval; - if (optlen<1) - goto e_inval; - if (val==-1) - val = 1; - if (val < 0 || val > 255) - goto e_inval; - inet->mc_ttl = val; - break; - case IP_MULTICAST_LOOP: - if (optlen<1) - goto e_inval; - inet->mc_loop = !!val; - break; - case IP_MULTICAST_IF: - { - struct ip_mreqn mreq; - struct net_device *dev = NULL; + dev = ip_dev_find(mreq.imr_address.s_addr); + if (dev) { + mreq.imr_ifindex = dev->ifindex; + dev_put(dev); + } + } else + dev = __dev_get_by_index(mreq.imr_ifindex); - if (sk->sk_type == SOCK_STREAM) - goto e_inval; - /* - * Check the arguments are allowable - */ - err = -EFAULT; - if (optlen >= sizeof(struct ip_mreqn)) { - if (copy_from_user(&mreq,optval,sizeof(mreq))) - break; - } else { - memset(&mreq, 0, sizeof(mreq)); - if (optlen >= sizeof(struct in_addr) && - copy_from_user(&mreq.imr_address,optval,sizeof(struct in_addr))) - break; - } + err = -EADDRNOTAVAIL; + if (!dev) + break; + + err = -EINVAL; + if (sk->sk_bound_dev_if && + mreq.imr_ifindex != sk->sk_bound_dev_if) + break; - if (!mreq.imr_ifindex) { - if (mreq.imr_address.s_addr == INADDR_ANY) { - inet->mc_index = 0; - inet->mc_addr = 0; - err = 0; - break; - } - dev = ip_dev_find(mreq.imr_address.s_addr); - if (dev) { - mreq.imr_ifindex = dev->ifindex; - dev_put(dev); - } - } else - dev = __dev_get_by_index(mreq.imr_ifindex); + inet->mc_index = mreq.imr_ifindex; + inet->mc_addr = mreq.imr_address.s_addr; + err = 0; + break; + } + case IP_ADD_MEMBERSHIP: + case IP_DROP_MEMBERSHIP: + { + struct ip_mreqn mreq; - err = -EADDRNOTAVAIL; - if (!dev) + if (optlen < sizeof(struct ip_mreq)) + goto e_inval; + err = -EFAULT; + if (optlen >= sizeof(struct ip_mreqn)) { + if (copy_from_user(&mreq,optval,sizeof(mreq))) break; - - err = -EINVAL; - if (sk->sk_bound_dev_if && - mreq.imr_ifindex != sk->sk_bound_dev_if) + } else { + memset(&mreq, 0, sizeof(mreq)); + if (copy_from_user(&mreq,optval,sizeof(struct ip_mreq))) break; + } - inet->mc_index = mreq.imr_ifindex; - inet->mc_addr = mreq.imr_address.s_addr; - err = 0; + if (optname == IP_ADD_MEMBERSHIP) + err = ip_mc_join_group(sk, &mreq); + else + err = ip_mc_leave_group(sk, &mreq); + break; + } + case IP_MSFILTER: + { + extern int sysctl_igmp_max_msf; + struct ip_msfilter *msf; + + if (optlen < IP_MSFILTER_SIZE(0)) + goto e_inval; + if (optlen > sysctl_optmem_max) { + err = -ENOBUFS; break; } + msf = kmalloc(optlen, GFP_KERNEL); + if (msf == 0) { + err = -ENOBUFS; + break; + } + err = -EFAULT; + if (copy_from_user(msf, optval, optlen)) { + kfree(msf); + break; + } + /* numsrc >= (1G-4) overflow in 32 bits */ + if (msf->imsf_numsrc >= 0x3ffffffcU || + msf->imsf_numsrc > sysctl_igmp_max_msf) { + kfree(msf); + err = -ENOBUFS; + break; + } + if (IP_MSFILTER_SIZE(msf->imsf_numsrc) > optlen) { + kfree(msf); + err = -EINVAL; + break; + } + err = ip_mc_msfilter(sk, msf, 0); + kfree(msf); + break; + } + case IP_BLOCK_SOURCE: + case IP_UNBLOCK_SOURCE: + case IP_ADD_SOURCE_MEMBERSHIP: + case IP_DROP_SOURCE_MEMBERSHIP: + { + struct ip_mreq_source mreqs; + int omode, add; - case IP_ADD_MEMBERSHIP: - case IP_DROP_MEMBERSHIP: - { - struct ip_mreqn mreq; - - if (optlen < sizeof(struct ip_mreq)) - goto e_inval; + if (optlen != sizeof(struct ip_mreq_source)) + goto e_inval; + if (copy_from_user(&mreqs, optval, sizeof(mreqs))) { err = -EFAULT; - if (optlen >= sizeof(struct ip_mreqn)) { - if(copy_from_user(&mreq,optval,sizeof(mreq))) - break; - } else { - memset(&mreq, 0, sizeof(mreq)); - if (copy_from_user(&mreq,optval,sizeof(struct ip_mreq))) - break; - } - - if (optname == IP_ADD_MEMBERSHIP) - err = ip_mc_join_group(sk, &mreq); - else - err = ip_mc_leave_group(sk, &mreq); break; } - case IP_MSFILTER: - { - extern int sysctl_igmp_max_msf; - struct ip_msfilter *msf; + if (optname == IP_BLOCK_SOURCE) { + omode = MCAST_EXCLUDE; + add = 1; + } else if (optname == IP_UNBLOCK_SOURCE) { + omode = MCAST_EXCLUDE; + add = 0; + } else if (optname == IP_ADD_SOURCE_MEMBERSHIP) { + struct ip_mreqn mreq; - if (optlen < IP_MSFILTER_SIZE(0)) - goto e_inval; - if (optlen > sysctl_optmem_max) { - err = -ENOBUFS; - break; - } - msf = kmalloc(optlen, GFP_KERNEL); - if (msf == 0) { - err = -ENOBUFS; + mreq.imr_multiaddr.s_addr = mreqs.imr_multiaddr; + mreq.imr_address.s_addr = mreqs.imr_interface; + mreq.imr_ifindex = 0; + err = ip_mc_join_group(sk, &mreq); + if (err && err != -EADDRINUSE) break; - } + omode = MCAST_INCLUDE; + add = 1; + } else /* IP_DROP_SOURCE_MEMBERSHIP */ { + omode = MCAST_INCLUDE; + add = 0; + } + err = ip_mc_source(add, omode, sk, &mreqs, 0); + break; + } + case MCAST_JOIN_GROUP: + case MCAST_LEAVE_GROUP: + { + struct group_req greq; + struct sockaddr_in *psin; + struct ip_mreqn mreq; + + if (optlen < sizeof(struct group_req)) + goto e_inval; + err = -EFAULT; + if (copy_from_user(&greq, optval, sizeof(greq))) + break; + psin = (struct sockaddr_in *)&greq.gr_group; + if (psin->sin_family != AF_INET) + goto e_inval; + memset(&mreq, 0, sizeof(mreq)); + mreq.imr_multiaddr = psin->sin_addr; + mreq.imr_ifindex = greq.gr_interface; + + if (optname == MCAST_JOIN_GROUP) + err = ip_mc_join_group(sk, &mreq); + else + err = ip_mc_leave_group(sk, &mreq); + break; + } + case MCAST_JOIN_SOURCE_GROUP: + case MCAST_LEAVE_SOURCE_GROUP: + case MCAST_BLOCK_SOURCE: + case MCAST_UNBLOCK_SOURCE: + { + struct group_source_req greqs; + struct ip_mreq_source mreqs; + struct sockaddr_in *psin; + int omode, add; + + if (optlen != sizeof(struct group_source_req)) + goto e_inval; + if (copy_from_user(&greqs, optval, sizeof(greqs))) { err = -EFAULT; - if (copy_from_user(msf, optval, optlen)) { - kfree(msf); - break; - } - /* numsrc >= (1G-4) overflow in 32 bits */ - if (msf->imsf_numsrc >= 0x3ffffffcU || - msf->imsf_numsrc > sysctl_igmp_max_msf) { - kfree(msf); - err = -ENOBUFS; - break; - } - if (IP_MSFILTER_SIZE(msf->imsf_numsrc) > optlen) { - kfree(msf); - err = -EINVAL; - break; - } - err = ip_mc_msfilter(sk, msf, 0); - kfree(msf); break; } - case IP_BLOCK_SOURCE: - case IP_UNBLOCK_SOURCE: - case IP_ADD_SOURCE_MEMBERSHIP: - case IP_DROP_SOURCE_MEMBERSHIP: - { - struct ip_mreq_source mreqs; - int omode, add; - - if (optlen != sizeof(struct ip_mreq_source)) - goto e_inval; - if (copy_from_user(&mreqs, optval, sizeof(mreqs))) { - err = -EFAULT; - break; - } - if (optname == IP_BLOCK_SOURCE) { - omode = MCAST_EXCLUDE; - add = 1; - } else if (optname == IP_UNBLOCK_SOURCE) { - omode = MCAST_EXCLUDE; - add = 0; - } else if (optname == IP_ADD_SOURCE_MEMBERSHIP) { - struct ip_mreqn mreq; - - mreq.imr_multiaddr.s_addr = mreqs.imr_multiaddr; - mreq.imr_address.s_addr = mreqs.imr_interface; - mreq.imr_ifindex = 0; - err = ip_mc_join_group(sk, &mreq); - if (err && err != -EADDRINUSE) - break; - omode = MCAST_INCLUDE; - add = 1; - } else /* IP_DROP_SOURCE_MEMBERSHIP */ { - omode = MCAST_INCLUDE; - add = 0; - } - err = ip_mc_source(add, omode, sk, &mreqs, 0); + if (greqs.gsr_group.ss_family != AF_INET || + greqs.gsr_source.ss_family != AF_INET) { + err = -EADDRNOTAVAIL; break; } - case MCAST_JOIN_GROUP: - case MCAST_LEAVE_GROUP: - { - struct group_req greq; - struct sockaddr_in *psin; + psin = (struct sockaddr_in *)&greqs.gsr_group; + mreqs.imr_multiaddr = psin->sin_addr.s_addr; + psin = (struct sockaddr_in *)&greqs.gsr_source; + mreqs.imr_sourceaddr = psin->sin_addr.s_addr; + mreqs.imr_interface = 0; /* use index for mc_source */ + + if (optname == MCAST_BLOCK_SOURCE) { + omode = MCAST_EXCLUDE; + add = 1; + } else if (optname == MCAST_UNBLOCK_SOURCE) { + omode = MCAST_EXCLUDE; + add = 0; + } else if (optname == MCAST_JOIN_SOURCE_GROUP) { struct ip_mreqn mreq; - if (optlen < sizeof(struct group_req)) - goto e_inval; - err = -EFAULT; - if(copy_from_user(&greq, optval, sizeof(greq))) - break; - psin = (struct sockaddr_in *)&greq.gr_group; - if (psin->sin_family != AF_INET) - goto e_inval; - memset(&mreq, 0, sizeof(mreq)); + psin = (struct sockaddr_in *)&greqs.gsr_group; mreq.imr_multiaddr = psin->sin_addr; - mreq.imr_ifindex = greq.gr_interface; - - if (optname == MCAST_JOIN_GROUP) - err = ip_mc_join_group(sk, &mreq); - else - err = ip_mc_leave_group(sk, &mreq); + mreq.imr_address.s_addr = 0; + mreq.imr_ifindex = greqs.gsr_interface; + err = ip_mc_join_group(sk, &mreq); + if (err && err != -EADDRINUSE) + break; + greqs.gsr_interface = mreq.imr_ifindex; + omode = MCAST_INCLUDE; + add = 1; + } else /* MCAST_LEAVE_SOURCE_GROUP */ { + omode = MCAST_INCLUDE; + add = 0; + } + err = ip_mc_source(add, omode, sk, &mreqs, + greqs.gsr_interface); + break; + } + case MCAST_MSFILTER: + { + extern int sysctl_igmp_max_msf; + struct sockaddr_in *psin; + struct ip_msfilter *msf = NULL; + struct group_filter *gsf = NULL; + int msize, i, ifindex; + + if (optlen < GROUP_FILTER_SIZE(0)) + goto e_inval; + if (optlen > sysctl_optmem_max) { + err = -ENOBUFS; break; } - case MCAST_JOIN_SOURCE_GROUP: - case MCAST_LEAVE_SOURCE_GROUP: - case MCAST_BLOCK_SOURCE: - case MCAST_UNBLOCK_SOURCE: - { - struct group_source_req greqs; - struct ip_mreq_source mreqs; - struct sockaddr_in *psin; - int omode, add; - - if (optlen != sizeof(struct group_source_req)) - goto e_inval; - if (copy_from_user(&greqs, optval, sizeof(greqs))) { - err = -EFAULT; - break; - } - if (greqs.gsr_group.ss_family != AF_INET || - greqs.gsr_source.ss_family != AF_INET) { - err = -EADDRNOTAVAIL; - break; - } - psin = (struct sockaddr_in *)&greqs.gsr_group; - mreqs.imr_multiaddr = psin->sin_addr.s_addr; - psin = (struct sockaddr_in *)&greqs.gsr_source; - mreqs.imr_sourceaddr = psin->sin_addr.s_addr; - mreqs.imr_interface = 0; /* use index for mc_source */ - - if (optname == MCAST_BLOCK_SOURCE) { - omode = MCAST_EXCLUDE; - add = 1; - } else if (optname == MCAST_UNBLOCK_SOURCE) { - omode = MCAST_EXCLUDE; - add = 0; - } else if (optname == MCAST_JOIN_SOURCE_GROUP) { - struct ip_mreqn mreq; - - psin = (struct sockaddr_in *)&greqs.gsr_group; - mreq.imr_multiaddr = psin->sin_addr; - mreq.imr_address.s_addr = 0; - mreq.imr_ifindex = greqs.gsr_interface; - err = ip_mc_join_group(sk, &mreq); - if (err && err != -EADDRINUSE) - break; - greqs.gsr_interface = mreq.imr_ifindex; - omode = MCAST_INCLUDE; - add = 1; - } else /* MCAST_LEAVE_SOURCE_GROUP */ { - omode = MCAST_INCLUDE; - add = 0; - } - err = ip_mc_source(add, omode, sk, &mreqs, - greqs.gsr_interface); + gsf = kmalloc(optlen,GFP_KERNEL); + if (gsf == 0) { + err = -ENOBUFS; break; } - case MCAST_MSFILTER: - { - extern int sysctl_igmp_max_msf; - struct sockaddr_in *psin; - struct ip_msfilter *msf = NULL; - struct group_filter *gsf = NULL; - int msize, i, ifindex; - - if (optlen < GROUP_FILTER_SIZE(0)) - goto e_inval; - if (optlen > sysctl_optmem_max) { - err = -ENOBUFS; - break; - } - gsf = kmalloc(optlen,GFP_KERNEL); - if (gsf == 0) { - err = -ENOBUFS; - break; - } - err = -EFAULT; - if (copy_from_user(gsf, optval, optlen)) { - goto mc_msf_out; - } - /* numsrc >= (4G-140)/128 overflow in 32 bits */ - if (gsf->gf_numsrc >= 0x1ffffff || - gsf->gf_numsrc > sysctl_igmp_max_msf) { - err = -ENOBUFS; - goto mc_msf_out; - } - if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) { - err = -EINVAL; - goto mc_msf_out; - } - msize = IP_MSFILTER_SIZE(gsf->gf_numsrc); - msf = kmalloc(msize,GFP_KERNEL); - if (msf == 0) { - err = -ENOBUFS; - goto mc_msf_out; - } - ifindex = gsf->gf_interface; - psin = (struct sockaddr_in *)&gsf->gf_group; - if (psin->sin_family != AF_INET) { - err = -EADDRNOTAVAIL; - goto mc_msf_out; - } - msf->imsf_multiaddr = psin->sin_addr.s_addr; - msf->imsf_interface = 0; - msf->imsf_fmode = gsf->gf_fmode; - msf->imsf_numsrc = gsf->gf_numsrc; + err = -EFAULT; + if (copy_from_user(gsf, optval, optlen)) { + goto mc_msf_out; + } + /* numsrc >= (4G-140)/128 overflow in 32 bits */ + if (gsf->gf_numsrc >= 0x1ffffff || + gsf->gf_numsrc > sysctl_igmp_max_msf) { + err = -ENOBUFS; + goto mc_msf_out; + } + if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) { + err = -EINVAL; + goto mc_msf_out; + } + msize = IP_MSFILTER_SIZE(gsf->gf_numsrc); + msf = kmalloc(msize,GFP_KERNEL); + if (msf == 0) { + err = -ENOBUFS; + goto mc_msf_out; + } + ifindex = gsf->gf_interface; + psin = (struct sockaddr_in *)&gsf->gf_group; + if (psin->sin_family != AF_INET) { err = -EADDRNOTAVAIL; - for (i=0; igf_numsrc; ++i) { - psin = (struct sockaddr_in *)&gsf->gf_slist[i]; - - if (psin->sin_family != AF_INET) - goto mc_msf_out; - msf->imsf_slist[i] = psin->sin_addr.s_addr; - } - kfree(gsf); - gsf = NULL; - - err = ip_mc_msfilter(sk, msf, ifindex); -mc_msf_out: - kfree(msf); - kfree(gsf); - break; + goto mc_msf_out; } - case IP_ROUTER_ALERT: - err = ip_ra_control(sk, val ? 1 : 0, NULL); - break; + msf->imsf_multiaddr = psin->sin_addr.s_addr; + msf->imsf_interface = 0; + msf->imsf_fmode = gsf->gf_fmode; + msf->imsf_numsrc = gsf->gf_numsrc; + err = -EADDRNOTAVAIL; + for (i=0; igf_numsrc; ++i) { + psin = (struct sockaddr_in *)&gsf->gf_slist[i]; - case IP_FREEBIND: - if (optlen<1) - goto e_inval; - inet->freebind = !!val; - break; - - case IP_IPSEC_POLICY: - case IP_XFRM_POLICY: - err = -EPERM; - if (!capable(CAP_NET_ADMIN)) - break; - err = xfrm_user_policy(sk, optname, optval, optlen); + if (psin->sin_family != AF_INET) + goto mc_msf_out; + msf->imsf_slist[i] = psin->sin_addr.s_addr; + } + kfree(gsf); + gsf = NULL; + + err = ip_mc_msfilter(sk, msf, ifindex); + mc_msf_out: + kfree(msf); + kfree(gsf); + break; + } + case IP_ROUTER_ALERT: + err = ip_ra_control(sk, val ? 1 : 0, NULL); + break; + + case IP_FREEBIND: + if (optlen<1) + goto e_inval; + inet->freebind = !!val; + break; + + case IP_IPSEC_POLICY: + case IP_XFRM_POLICY: + err = -EPERM; + if (!capable(CAP_NET_ADMIN)) break; + err = xfrm_user_policy(sk, optname, optval, optlen); + break; - default: - err = -ENOPROTOOPT; - break; + default: + err = -ENOPROTOOPT; + break; } release_sock(sk); return err; @@ -948,214 +948,213 @@ EXPORT_SYMBOL(compat_ip_setsockopt); */ static int do_ip_getsockopt(struct sock *sk, int level, int optname, - char __user *optval, int __user *optlen) + char __user *optval, int __user *optlen) { struct inet_sock *inet = inet_sk(sk); int val; int len; - if(level!=SOL_IP) + if (level != SOL_IP) return -EOPNOTSUPP; #ifdef CONFIG_IP_MROUTE - if(optname>=MRT_BASE && optname <=MRT_BASE+10) - { + if (optname >= MRT_BASE && optname <= MRT_BASE+10) { return ip_mroute_getsockopt(sk,optname,optval,optlen); } #endif - if(get_user(len,optlen)) + if (get_user(len,optlen)) return -EFAULT; - if(len < 0) + if (len < 0) return -EINVAL; lock_sock(sk); - switch(optname) { - case IP_OPTIONS: - { - unsigned char optbuf[sizeof(struct ip_options)+40]; - struct ip_options * opt = (struct ip_options*)optbuf; - opt->optlen = 0; - if (inet->opt) - memcpy(optbuf, inet->opt, - sizeof(struct ip_options)+ - inet->opt->optlen); - release_sock(sk); - - if (opt->optlen == 0) - return put_user(0, optlen); - - ip_options_undo(opt); - - len = min_t(unsigned int, len, opt->optlen); - if(put_user(len, optlen)) - return -EFAULT; - if(copy_to_user(optval, opt->__data, len)) - return -EFAULT; - return 0; - } - case IP_PKTINFO: - val = (inet->cmsg_flags & IP_CMSG_PKTINFO) != 0; - break; - case IP_RECVTTL: - val = (inet->cmsg_flags & IP_CMSG_TTL) != 0; - break; - case IP_RECVTOS: - val = (inet->cmsg_flags & IP_CMSG_TOS) != 0; - break; - case IP_RECVOPTS: - val = (inet->cmsg_flags & IP_CMSG_RECVOPTS) != 0; - break; - case IP_RETOPTS: - val = (inet->cmsg_flags & IP_CMSG_RETOPTS) != 0; - break; - case IP_PASSSEC: - val = (inet->cmsg_flags & IP_CMSG_PASSSEC) != 0; - break; - case IP_TOS: - val = inet->tos; - break; - case IP_TTL: - val = (inet->uc_ttl == -1 ? - sysctl_ip_default_ttl : - inet->uc_ttl); - break; - case IP_HDRINCL: - val = inet->hdrincl; - break; - case IP_MTU_DISCOVER: - val = inet->pmtudisc; - break; - case IP_MTU: - { - struct dst_entry *dst; - val = 0; - dst = sk_dst_get(sk); - if (dst) { - val = dst_mtu(dst); - dst_release(dst); - } - if (!val) { - release_sock(sk); - return -ENOTCONN; - } - break; + switch (optname) { + case IP_OPTIONS: + { + unsigned char optbuf[sizeof(struct ip_options)+40]; + struct ip_options * opt = (struct ip_options*)optbuf; + opt->optlen = 0; + if (inet->opt) + memcpy(optbuf, inet->opt, + sizeof(struct ip_options)+ + inet->opt->optlen); + release_sock(sk); + + if (opt->optlen == 0) + return put_user(0, optlen); + + ip_options_undo(opt); + + len = min_t(unsigned int, len, opt->optlen); + if (put_user(len, optlen)) + return -EFAULT; + if (copy_to_user(optval, opt->__data, len)) + return -EFAULT; + return 0; + } + case IP_PKTINFO: + val = (inet->cmsg_flags & IP_CMSG_PKTINFO) != 0; + break; + case IP_RECVTTL: + val = (inet->cmsg_flags & IP_CMSG_TTL) != 0; + break; + case IP_RECVTOS: + val = (inet->cmsg_flags & IP_CMSG_TOS) != 0; + break; + case IP_RECVOPTS: + val = (inet->cmsg_flags & IP_CMSG_RECVOPTS) != 0; + break; + case IP_RETOPTS: + val = (inet->cmsg_flags & IP_CMSG_RETOPTS) != 0; + break; + case IP_PASSSEC: + val = (inet->cmsg_flags & IP_CMSG_PASSSEC) != 0; + break; + case IP_TOS: + val = inet->tos; + break; + case IP_TTL: + val = (inet->uc_ttl == -1 ? + sysctl_ip_default_ttl : + inet->uc_ttl); + break; + case IP_HDRINCL: + val = inet->hdrincl; + break; + case IP_MTU_DISCOVER: + val = inet->pmtudisc; + break; + case IP_MTU: + { + struct dst_entry *dst; + val = 0; + dst = sk_dst_get(sk); + if (dst) { + val = dst_mtu(dst); + dst_release(dst); } - case IP_RECVERR: - val = inet->recverr; - break; - case IP_MULTICAST_TTL: - val = inet->mc_ttl; - break; - case IP_MULTICAST_LOOP: - val = inet->mc_loop; - break; - case IP_MULTICAST_IF: - { - struct in_addr addr; - len = min_t(unsigned int, len, sizeof(struct in_addr)); - addr.s_addr = inet->mc_addr; + if (!val) { release_sock(sk); - - if(put_user(len, optlen)) - return -EFAULT; - if(copy_to_user(optval, &addr, len)) - return -EFAULT; - return 0; + return -ENOTCONN; } - case IP_MSFILTER: - { - struct ip_msfilter msf; - int err; + break; + } + case IP_RECVERR: + val = inet->recverr; + break; + case IP_MULTICAST_TTL: + val = inet->mc_ttl; + break; + case IP_MULTICAST_LOOP: + val = inet->mc_loop; + break; + case IP_MULTICAST_IF: + { + struct in_addr addr; + len = min_t(unsigned int, len, sizeof(struct in_addr)); + addr.s_addr = inet->mc_addr; + release_sock(sk); - if (len < IP_MSFILTER_SIZE(0)) { - release_sock(sk); - return -EINVAL; - } - if (copy_from_user(&msf, optval, IP_MSFILTER_SIZE(0))) { - release_sock(sk); - return -EFAULT; - } - err = ip_mc_msfget(sk, &msf, - (struct ip_msfilter __user *)optval, optlen); + if (put_user(len, optlen)) + return -EFAULT; + if (copy_to_user(optval, &addr, len)) + return -EFAULT; + return 0; + } + case IP_MSFILTER: + { + struct ip_msfilter msf; + int err; + + if (len < IP_MSFILTER_SIZE(0)) { release_sock(sk); - return err; + return -EINVAL; } - case MCAST_MSFILTER: - { - struct group_filter gsf; - int err; - - if (len < GROUP_FILTER_SIZE(0)) { - release_sock(sk); - return -EINVAL; - } - if (copy_from_user(&gsf, optval, GROUP_FILTER_SIZE(0))) { - release_sock(sk); - return -EFAULT; - } - err = ip_mc_gsfget(sk, &gsf, - (struct group_filter __user *)optval, optlen); + if (copy_from_user(&msf, optval, IP_MSFILTER_SIZE(0))) { release_sock(sk); - return err; + return -EFAULT; } - case IP_PKTOPTIONS: - { - struct msghdr msg; + err = ip_mc_msfget(sk, &msf, + (struct ip_msfilter __user *)optval, optlen); + release_sock(sk); + return err; + } + case MCAST_MSFILTER: + { + struct group_filter gsf; + int err; + if (len < GROUP_FILTER_SIZE(0)) { release_sock(sk); + return -EINVAL; + } + if (copy_from_user(&gsf, optval, GROUP_FILTER_SIZE(0))) { + release_sock(sk); + return -EFAULT; + } + err = ip_mc_gsfget(sk, &gsf, + (struct group_filter __user *)optval, optlen); + release_sock(sk); + return err; + } + case IP_PKTOPTIONS: + { + struct msghdr msg; + + release_sock(sk); - if (sk->sk_type != SOCK_STREAM) - return -ENOPROTOOPT; + if (sk->sk_type != SOCK_STREAM) + return -ENOPROTOOPT; - msg.msg_control = optval; - msg.msg_controllen = len; - msg.msg_flags = 0; + msg.msg_control = optval; + msg.msg_controllen = len; + msg.msg_flags = 0; - if (inet->cmsg_flags & IP_CMSG_PKTINFO) { - struct in_pktinfo info; + if (inet->cmsg_flags & IP_CMSG_PKTINFO) { + struct in_pktinfo info; - info.ipi_addr.s_addr = inet->rcv_saddr; - info.ipi_spec_dst.s_addr = inet->rcv_saddr; - info.ipi_ifindex = inet->mc_index; - put_cmsg(&msg, SOL_IP, IP_PKTINFO, sizeof(info), &info); - } - if (inet->cmsg_flags & IP_CMSG_TTL) { - int hlim = inet->mc_ttl; - put_cmsg(&msg, SOL_IP, IP_TTL, sizeof(hlim), &hlim); - } - len -= msg.msg_controllen; - return put_user(len, optlen); + info.ipi_addr.s_addr = inet->rcv_saddr; + info.ipi_spec_dst.s_addr = inet->rcv_saddr; + info.ipi_ifindex = inet->mc_index; + put_cmsg(&msg, SOL_IP, IP_PKTINFO, sizeof(info), &info); } - case IP_FREEBIND: - val = inet->freebind; - break; - default: - release_sock(sk); - return -ENOPROTOOPT; + if (inet->cmsg_flags & IP_CMSG_TTL) { + int hlim = inet->mc_ttl; + put_cmsg(&msg, SOL_IP, IP_TTL, sizeof(hlim), &hlim); + } + len -= msg.msg_controllen; + return put_user(len, optlen); + } + case IP_FREEBIND: + val = inet->freebind; + break; + default: + release_sock(sk); + return -ENOPROTOOPT; } release_sock(sk); if (len < sizeof(int) && len > 0 && val>=0 && val<255) { unsigned char ucval = (unsigned char)val; len = 1; - if(put_user(len, optlen)) + if (put_user(len, optlen)) return -EFAULT; - if(copy_to_user(optval,&ucval,1)) + if (copy_to_user(optval,&ucval,1)) return -EFAULT; } else { len = min_t(unsigned int, sizeof(int), len); - if(put_user(len, optlen)) + if (put_user(len, optlen)) return -EFAULT; - if(copy_to_user(optval,&val,len)) + if (copy_to_user(optval,&val,len)) return -EFAULT; } return 0; } int ip_getsockopt(struct sock *sk, int level, - int optname, char __user *optval, int __user *optlen) + int optname, char __user *optval, int __user *optlen) { int err; @@ -1169,7 +1168,7 @@ int ip_getsockopt(struct sock *sk, int level, ) { int len; - if(get_user(len,optlen)) + if (get_user(len,optlen)) return -EFAULT; lock_sock(sk); diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index cf49de1a4983..c43699f374cd 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -782,7 +782,7 @@ static void __init ic_do_bootp_ext(u8 *ext) u8 *c; printk("DHCP/BOOTP: Got extension %d:",*ext); - for(c=ext+2; cable & IC_BOOTP)) ic_bootp_send_if(d, jiffies - start_jiffies); diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 601e3df69258..f73f4e402f72 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -302,7 +302,7 @@ static void ipmr_destroy_unres(struct mfc_cache *c) atomic_dec(&cache_resolve_queue_len); - while((skb=skb_dequeue(&c->mfc_un.unres.unresolved))) { + while ((skb=skb_dequeue(&c->mfc_un.unres.unresolved))) { if (skb->nh.iph->version == 0) { struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr)); nlh->nlmsg_type = NLMSG_ERROR; @@ -479,7 +479,7 @@ static struct mfc_cache *ipmr_cache_find(__be32 origin, __be32 mcastgrp) static struct mfc_cache *ipmr_cache_alloc(void) { struct mfc_cache *c=kmem_cache_zalloc(mrt_cachep, GFP_KERNEL); - if(c==NULL) + if (c==NULL) return NULL; c->mfc_un.res.minvif = MAXVIFS; return c; @@ -488,7 +488,7 @@ static struct mfc_cache *ipmr_cache_alloc(void) static struct mfc_cache *ipmr_cache_alloc_unres(void) { struct mfc_cache *c=kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC); - if(c==NULL) + if (c==NULL) return NULL; skb_queue_head_init(&c->mfc_un.unres.unresolved); c->mfc_un.unres.expires = jiffies + 10*HZ; @@ -508,7 +508,7 @@ static void ipmr_cache_resolve(struct mfc_cache *uc, struct mfc_cache *c) * Play the pending entries through our router */ - while((skb=__skb_dequeue(&uc->mfc_un.unres.unresolved))) { + while ((skb=__skb_dequeue(&uc->mfc_un.unres.unresolved))) { if (skb->nh.iph->version == 0) { struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr)); @@ -551,7 +551,7 @@ static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert) #endif skb = alloc_skb(128, GFP_ATOMIC); - if(!skb) + if (!skb) return -ENOBUFS; #ifdef CONFIG_IP_PIMSM @@ -734,7 +734,7 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) return 0; } - if(!MULTICAST(mfc->mfcc_mcastgrp.s_addr)) + if (!MULTICAST(mfc->mfcc_mcastgrp.s_addr)) return -EINVAL; c=ipmr_cache_alloc(); @@ -788,7 +788,7 @@ static void mroute_clean_tables(struct sock *sk) /* * Shut down all active vif entries */ - for(i=0; isk_type != SOCK_RAW || - inet_sk(sk)->num != IPPROTO_IGMP) - return -EOPNOTSUPP; - if(optlen!=sizeof(int)) - return -ENOPROTOOPT; - - rtnl_lock(); - if (mroute_socket) { - rtnl_unlock(); - return -EADDRINUSE; - } - - ret = ip_ra_control(sk, 1, mrtsock_destruct); - if (ret == 0) { - write_lock_bh(&mrt_lock); - mroute_socket=sk; - write_unlock_bh(&mrt_lock); + switch (optname) { + case MRT_INIT: + if (sk->sk_type != SOCK_RAW || + inet_sk(sk)->num != IPPROTO_IGMP) + return -EOPNOTSUPP; + if (optlen!=sizeof(int)) + return -ENOPROTOOPT; - ipv4_devconf.mc_forwarding++; - } + rtnl_lock(); + if (mroute_socket) { rtnl_unlock(); - return ret; - case MRT_DONE: - if (sk!=mroute_socket) - return -EACCES; - return ip_ra_control(sk, 0, NULL); - case MRT_ADD_VIF: - case MRT_DEL_VIF: - if(optlen!=sizeof(vif)) - return -EINVAL; - if (copy_from_user(&vif,optval,sizeof(vif))) - return -EFAULT; - if(vif.vifc_vifi >= MAXVIFS) - return -ENFILE; - rtnl_lock(); - if (optname==MRT_ADD_VIF) { - ret = vif_add(&vif, sk==mroute_socket); - } else { - ret = vif_delete(vif.vifc_vifi); - } - rtnl_unlock(); - return ret; + return -EADDRINUSE; + } + + ret = ip_ra_control(sk, 1, mrtsock_destruct); + if (ret == 0) { + write_lock_bh(&mrt_lock); + mroute_socket=sk; + write_unlock_bh(&mrt_lock); + + ipv4_devconf.mc_forwarding++; + } + rtnl_unlock(); + return ret; + case MRT_DONE: + if (sk!=mroute_socket) + return -EACCES; + return ip_ra_control(sk, 0, NULL); + case MRT_ADD_VIF: + case MRT_DEL_VIF: + if (optlen!=sizeof(vif)) + return -EINVAL; + if (copy_from_user(&vif,optval,sizeof(vif))) + return -EFAULT; + if (vif.vifc_vifi >= MAXVIFS) + return -ENFILE; + rtnl_lock(); + if (optname==MRT_ADD_VIF) { + ret = vif_add(&vif, sk==mroute_socket); + } else { + ret = vif_delete(vif.vifc_vifi); + } + rtnl_unlock(); + return ret; /* * Manipulate the forwarding caches. These live * in a sort of kernel/user symbiosis. */ - case MRT_ADD_MFC: - case MRT_DEL_MFC: - if(optlen!=sizeof(mfc)) - return -EINVAL; - if (copy_from_user(&mfc,optval, sizeof(mfc))) - return -EFAULT; - rtnl_lock(); - if (optname==MRT_DEL_MFC) - ret = ipmr_mfc_delete(&mfc); - else - ret = ipmr_mfc_add(&mfc, sk==mroute_socket); - rtnl_unlock(); - return ret; + case MRT_ADD_MFC: + case MRT_DEL_MFC: + if (optlen!=sizeof(mfc)) + return -EINVAL; + if (copy_from_user(&mfc,optval, sizeof(mfc))) + return -EFAULT; + rtnl_lock(); + if (optname==MRT_DEL_MFC) + ret = ipmr_mfc_delete(&mfc); + else + ret = ipmr_mfc_add(&mfc, sk==mroute_socket); + rtnl_unlock(); + return ret; /* * Control PIM assert. */ - case MRT_ASSERT: - { - int v; - if(get_user(v,(int __user *)optval)) - return -EFAULT; - mroute_do_assert=(v)?1:0; - return 0; - } + case MRT_ASSERT: + { + int v; + if (get_user(v,(int __user *)optval)) + return -EFAULT; + mroute_do_assert=(v)?1:0; + return 0; + } #ifdef CONFIG_IP_PIMSM - case MRT_PIM: - { - int v, ret; - if(get_user(v,(int __user *)optval)) - return -EFAULT; - v = (v)?1:0; - rtnl_lock(); - ret = 0; - if (v != mroute_do_pim) { - mroute_do_pim = v; - mroute_do_assert = v; + case MRT_PIM: + { + int v, ret; + if (get_user(v,(int __user *)optval)) + return -EFAULT; + v = (v)?1:0; + rtnl_lock(); + ret = 0; + if (v != mroute_do_pim) { + mroute_do_pim = v; + mroute_do_assert = v; #ifdef CONFIG_IP_PIMSM_V2 - if (mroute_do_pim) - ret = inet_add_protocol(&pim_protocol, - IPPROTO_PIM); - else - ret = inet_del_protocol(&pim_protocol, - IPPROTO_PIM); - if (ret < 0) - ret = -EAGAIN; + if (mroute_do_pim) + ret = inet_add_protocol(&pim_protocol, + IPPROTO_PIM); + else + ret = inet_del_protocol(&pim_protocol, + IPPROTO_PIM); + if (ret < 0) + ret = -EAGAIN; #endif - } - rtnl_unlock(); - return ret; } + rtnl_unlock(); + return ret; + } #endif - /* - * Spurious command, or MRT_VERSION which you cannot - * set. - */ - default: - return -ENOPROTOOPT; + /* + * Spurious command, or MRT_VERSION which you cannot + * set. + */ + default: + return -ENOPROTOOPT; } } @@ -983,7 +981,7 @@ int ip_mroute_getsockopt(struct sock *sk,int optname,char __user *optval,int __u int olr; int val; - if(optname!=MRT_VERSION && + if (optname!=MRT_VERSION && #ifdef CONFIG_IP_PIMSM optname!=MRT_PIM && #endif @@ -997,17 +995,17 @@ int ip_mroute_getsockopt(struct sock *sk,int optname,char __user *optval,int __u if (olr < 0) return -EINVAL; - if(put_user(olr,optlen)) + if (put_user(olr,optlen)) return -EFAULT; - if(optname==MRT_VERSION) + if (optname==MRT_VERSION) val=0x0305; #ifdef CONFIG_IP_PIMSM - else if(optname==MRT_PIM) + else if (optname==MRT_PIM) val=mroute_do_pim; #endif else val=mroute_do_assert; - if(copy_to_user(optval,&val,olr)) + if (copy_to_user(optval,&val,olr)) return -EFAULT; return 0; } @@ -1023,48 +1021,47 @@ int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg) struct vif_device *vif; struct mfc_cache *c; - switch(cmd) - { - case SIOCGETVIFCNT: - if (copy_from_user(&vr,arg,sizeof(vr))) - return -EFAULT; - if(vr.vifi>=maxvif) - return -EINVAL; - read_lock(&mrt_lock); - vif=&vif_table[vr.vifi]; - if(VIF_EXISTS(vr.vifi)) { - vr.icount=vif->pkt_in; - vr.ocount=vif->pkt_out; - vr.ibytes=vif->bytes_in; - vr.obytes=vif->bytes_out; - read_unlock(&mrt_lock); - - if (copy_to_user(arg,&vr,sizeof(vr))) - return -EFAULT; - return 0; - } + switch (cmd) { + case SIOCGETVIFCNT: + if (copy_from_user(&vr,arg,sizeof(vr))) + return -EFAULT; + if (vr.vifi>=maxvif) + return -EINVAL; + read_lock(&mrt_lock); + vif=&vif_table[vr.vifi]; + if (VIF_EXISTS(vr.vifi)) { + vr.icount=vif->pkt_in; + vr.ocount=vif->pkt_out; + vr.ibytes=vif->bytes_in; + vr.obytes=vif->bytes_out; read_unlock(&mrt_lock); - return -EADDRNOTAVAIL; - case SIOCGETSGCNT: - if (copy_from_user(&sr,arg,sizeof(sr))) - return -EFAULT; - read_lock(&mrt_lock); - c = ipmr_cache_find(sr.src.s_addr, sr.grp.s_addr); - if (c) { - sr.pktcnt = c->mfc_un.res.pkt; - sr.bytecnt = c->mfc_un.res.bytes; - sr.wrong_if = c->mfc_un.res.wrong_if; - read_unlock(&mrt_lock); - - if (copy_to_user(arg,&sr,sizeof(sr))) - return -EFAULT; - return 0; - } + if (copy_to_user(arg,&vr,sizeof(vr))) + return -EFAULT; + return 0; + } + read_unlock(&mrt_lock); + return -EADDRNOTAVAIL; + case SIOCGETSGCNT: + if (copy_from_user(&sr,arg,sizeof(sr))) + return -EFAULT; + + read_lock(&mrt_lock); + c = ipmr_cache_find(sr.src.s_addr, sr.grp.s_addr); + if (c) { + sr.pktcnt = c->mfc_un.res.pkt; + sr.bytecnt = c->mfc_un.res.bytes; + sr.wrong_if = c->mfc_un.res.wrong_if; read_unlock(&mrt_lock); - return -EADDRNOTAVAIL; - default: - return -ENOIOCTLCMD; + + if (copy_to_user(arg,&sr,sizeof(sr))) + return -EFAULT; + return 0; + } + read_unlock(&mrt_lock); + return -EADDRNOTAVAIL; + default: + return -ENOIOCTLCMD; } } @@ -1076,7 +1073,7 @@ static int ipmr_device_event(struct notifier_block *this, unsigned long event, v if (event != NETDEV_UNREGISTER) return NOTIFY_DONE; v=&vif_table[0]; - for(ct=0;ctdev==ptr) vif_delete(ct); } @@ -1625,7 +1622,7 @@ static struct vif_device *ipmr_vif_seq_idx(struct ipmr_vif_iter *iter, loff_t pos) { for (iter->ct = 0; iter->ct < maxvif; ++iter->ct) { - if(!VIF_EXISTS(iter->ct)) + if (!VIF_EXISTS(iter->ct)) continue; if (pos-- == 0) return &vif_table[iter->ct]; @@ -1649,7 +1646,7 @@ static void *ipmr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos) return ipmr_vif_seq_idx(iter, 0); while (++iter->ct < maxvif) { - if(!VIF_EXISTS(iter->ct)) + if (!VIF_EXISTS(iter->ct)) continue; return &vif_table[iter->ct]; } @@ -1732,14 +1729,14 @@ static struct mfc_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos) it->cache = mfc_cache_array; read_lock(&mrt_lock); for (it->ct = 0; it->ct < MFC_LINES; it->ct++) - for(mfc = mfc_cache_array[it->ct]; mfc; mfc = mfc->next) + for (mfc = mfc_cache_array[it->ct]; mfc; mfc = mfc->next) if (pos-- == 0) return mfc; read_unlock(&mrt_lock); it->cache = &mfc_unres_queue; spin_lock_bh(&mfc_unres_lock); - for(mfc = mfc_unres_queue; mfc; mfc = mfc->next) + for (mfc = mfc_unres_queue; mfc; mfc = mfc->next) if (pos-- == 0) return mfc; spin_unlock_bh(&mfc_unres_lock); @@ -1829,9 +1826,9 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) mfc->mfc_un.res.wrong_if); if (it->cache != &mfc_unres_queue) { - for(n = mfc->mfc_un.res.minvif; - n < mfc->mfc_un.res.maxvif; n++ ) { - if(VIF_EXISTS(n) + for (n = mfc->mfc_un.res.minvif; + n < mfc->mfc_un.res.maxvif; n++ ) { + if (VIF_EXISTS(n) && mfc->mfc_un.res.ttls[n] < 255) seq_printf(seq, " %2d:%-3d", diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c index ceb4376f572a..4872b30ba5d8 100644 --- a/net/ipv4/xfrm4_mode_tunnel.c +++ b/net/ipv4/xfrm4_mode_tunnel.c @@ -93,7 +93,7 @@ static int xfrm4_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) struct iphdr *iph = skb->nh.iph; int err = -EINVAL; - switch(iph->protocol){ + switch (iph->protocol){ case IPPROTO_IPIP: break; #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 5d51a2af34c1..98a833ce1114 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -119,7 +119,7 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int if (xfrm[i]->props.mode == XFRM_MODE_TUNNEL) { unsigned short encap_family = xfrm[i]->props.family; - switch(encap_family) { + switch (encap_family) { case AF_INET: fl_tunnel.fl4_dst = xfrm[i]->id.daddr.a4; fl_tunnel.fl4_src = xfrm[i]->props.saddr.a4; -- cgit v1.2.3 From 63f3444fb9a54c024d55f1205f8b94e7d2786595 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 22 Mar 2007 11:55:17 -0700 Subject: [IPv4]: Use rtnl registration interface Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- include/net/ip_fib.h | 6 ------ net/ipv4/devinet.c | 21 +++++---------------- net/ipv4/fib_frontend.c | 12 ++++++++---- net/ipv4/fib_rules.c | 4 +++- net/ipv4/route.c | 6 ++++-- 5 files changed, 20 insertions(+), 29 deletions(-) (limited to 'net/ipv4/devinet.c') diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 36c635ca1aa6..5a4a0366c24f 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -215,10 +215,6 @@ extern void fib_select_default(const struct flowi *flp, struct fib_result *res); /* Exported by fib_frontend.c */ extern struct nla_policy rtm_ipv4_policy[]; extern void ip_fib_init(void); -extern int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg); -extern int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg); -extern int inet_rtm_getroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg); -extern int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb); extern int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, struct net_device *dev, __be32 *spec_dst, u32 *itag); extern void fib_select_multipath(const struct flowi *flp, struct fib_result *res); @@ -235,8 +231,6 @@ extern __be32 __fib_res_prefsrc(struct fib_result *res); extern struct fib_table *fib_hash_init(u32 id); #ifdef CONFIG_IP_MULTIPLE_TABLES -extern int fib4_rules_dump(struct sk_buff *skb, struct netlink_callback *cb); - extern void __init fib4_rules_init(void); #ifdef CONFIG_NET_CLS_ROUTE diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 043857bd151c..9bdc79564cc6 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -48,7 +48,6 @@ #include #include #include -#include #include #include #include @@ -62,7 +61,7 @@ #include #include #include -#include +#include struct ipv4_devconf ipv4_devconf = { .accept_redirects = 1, @@ -1241,19 +1240,6 @@ errout: rtnl_set_sk_err(RTNLGRP_IPV4_IFADDR, err); } -static struct rtnetlink_link inet_rtnetlink_table[RTM_NR_MSGTYPES] = { - [RTM_NEWADDR - RTM_BASE] = { .doit = inet_rtm_newaddr, }, - [RTM_DELADDR - RTM_BASE] = { .doit = inet_rtm_deladdr, }, - [RTM_GETADDR - RTM_BASE] = { .dumpit = inet_dump_ifaddr, }, - [RTM_NEWROUTE - RTM_BASE] = { .doit = inet_rtm_newroute, }, - [RTM_DELROUTE - RTM_BASE] = { .doit = inet_rtm_delroute, }, - [RTM_GETROUTE - RTM_BASE] = { .doit = inet_rtm_getroute, - .dumpit = inet_dump_fib, }, -#ifdef CONFIG_IP_MULTIPLE_TABLES - [RTM_GETRULE - RTM_BASE] = { .dumpit = fib4_rules_dump, }, -#endif -}; - #ifdef CONFIG_SYSCTL void inet_forward_change(void) @@ -1636,7 +1622,10 @@ void __init devinet_init(void) { register_gifconf(PF_INET, inet_gifconf); register_netdevice_notifier(&ip_netdev_notifier); - rtnetlink_links[PF_INET] = inet_rtnetlink_table; + + rtnl_register(PF_INET, RTM_NEWADDR, inet_rtm_newaddr, NULL); + rtnl_register(PF_INET, RTM_DELADDR, inet_rtm_deladdr, NULL); + rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr); #ifdef CONFIG_SYSCTL devinet_sysctl.sysctl_header = register_sysctl_table(devinet_sysctl.devinet_root_dir); diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 3ff753c6f197..5bf718a3e49b 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include @@ -46,6 +45,7 @@ #include #include #include +#include #define FFprint(a...) printk(KERN_DEBUG a) @@ -540,7 +540,7 @@ errout: return err; } -int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) +static int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) { struct fib_config cfg; struct fib_table *tb; @@ -561,7 +561,7 @@ errout: return err; } -int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) +static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) { struct fib_config cfg; struct fib_table *tb; @@ -582,7 +582,7 @@ errout: return err; } -int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) +static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) { unsigned int h, s_h; unsigned int e = 0, s_e; @@ -925,6 +925,10 @@ void __init ip_fib_init(void) register_netdevice_notifier(&fib_netdev_notifier); register_inetaddr_notifier(&fib_inetaddr_notifier); nl_fib_lookup_init(); + + rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL); + rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL); + rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib); } EXPORT_SYMBOL(inet_addr_type); diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index c660c074c76c..a7f931ddfaad 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c @@ -274,7 +274,7 @@ nla_put_failure: return -ENOBUFS; } -int fib4_rules_dump(struct sk_buff *skb, struct netlink_callback *cb) +static int fib4_rule_dump(struct sk_buff *skb, struct netlink_callback *cb) { return fib_rules_dump(skb, cb, AF_INET); } @@ -327,4 +327,6 @@ void __init fib4_rules_init(void) list_add_tail(&default_rule.common.list, &fib4_rules); fib_rules_register(&fib4_rules_ops); + + rtnl_register(PF_INET, RTM_GETRULE, NULL, fib4_rule_dump); } diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 58417393dec1..df9fe4f2e8cc 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -82,7 +82,6 @@ #include #include #include -#include #include #include #include @@ -104,6 +103,7 @@ #include #include #include +#include #ifdef CONFIG_SYSCTL #include #endif @@ -2721,7 +2721,7 @@ nla_put_failure: return -EMSGSIZE; } -int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) +static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) { struct rtmsg *rtm; struct nlattr *tb[RTA_MAX+1]; @@ -3194,6 +3194,8 @@ int __init ip_rt_init(void) xfrm_init(); xfrm4_init(); #endif + rtnl_register(PF_INET, RTM_GETROUTE, inet_rtm_getroute, NULL); + return rc; } -- cgit v1.2.3 From 6313c1e0992feaee56bc09b85042b3186041fa3c Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 16 Apr 2007 17:00:53 -0700 Subject: [RTNETLINK]: Remove unnecessary locking in dump callbacks Since we're now holding the rtnl during the entire dump operation, we can remove additional locking for rtnl protected data. This patch does that for all simple cases (dev_base_lock for dev_base walking, RCU protection for FIB rule dumping). Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/bridge/br_netlink.c | 2 -- net/core/fib_rules.c | 4 +--- net/core/rtnetlink.c | 2 -- net/decnet/dn_dev.c | 3 --- net/ipv4/devinet.c | 12 ++---------- net/ipv6/addrconf.c | 2 -- 6 files changed, 3 insertions(+), 22 deletions(-) (limited to 'net/ipv4/devinet.c') diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 5e84ade129ca..35facc0c11c2 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -109,7 +109,6 @@ static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) struct net_device *dev; int idx; - read_lock(&dev_base_lock); for (dev = dev_base, idx = 0; dev; dev = dev->next) { /* not a bridge port */ if (dev->br_port == NULL || idx < cb->args[0]) @@ -122,7 +121,6 @@ static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) skip: ++idx; } - read_unlock(&dev_base_lock); cb->args[0] = idx; diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index cb2dae19531b..8c5474e16683 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -495,8 +495,7 @@ static int dump_rules(struct sk_buff *skb, struct netlink_callback *cb, int idx = 0; struct fib_rule *rule; - rcu_read_lock(); - list_for_each_entry_rcu(rule, ops->rules_list, list) { + list_for_each_entry(rule, ops->rules_list, list) { if (idx < cb->args[1]) goto skip; @@ -507,7 +506,6 @@ static int dump_rules(struct sk_buff *skb, struct netlink_callback *cb, skip: idx++; } - rcu_read_unlock(); cb->args[1] = idx; rules_ops_put(ops); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 62f5c7f98d17..bc95fab0b0ce 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -543,7 +543,6 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) int s_idx = cb->args[0]; struct net_device *dev; - read_lock(&dev_base_lock); for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) { if (idx < s_idx) continue; @@ -552,7 +551,6 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) cb->nlh->nlmsg_seq, 0, NLM_F_MULTI) <= 0) break; } - read_unlock(&dev_base_lock); cb->args[0] = idx; return skb->len; diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 61be2caddc57..5c2a9951b638 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -799,7 +799,6 @@ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) skip_ndevs = cb->args[0]; skip_naddr = cb->args[1]; - read_lock(&dev_base_lock); for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) { if (idx < skip_ndevs) continue; @@ -824,8 +823,6 @@ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) } } done: - read_unlock(&dev_base_lock); - cb->args[0] = idx; cb->args[1] = dn_idx; diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 9bdc79564cc6..088888db8b3d 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1182,17 +1182,13 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) int s_ip_idx, s_idx = cb->args[0]; s_ip_idx = ip_idx = cb->args[1]; - read_lock(&dev_base_lock); for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) { if (idx < s_idx) continue; if (idx > s_idx) s_ip_idx = 0; - rcu_read_lock(); - if ((in_dev = __in_dev_get_rcu(dev)) == NULL) { - rcu_read_unlock(); + if ((in_dev = __in_dev_get_rtnl(dev)) == NULL) continue; - } for (ifa = in_dev->ifa_list, ip_idx = 0; ifa; ifa = ifa->ifa_next, ip_idx++) { @@ -1200,16 +1196,12 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) continue; if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, - RTM_NEWADDR, NLM_F_MULTI) <= 0) { - rcu_read_unlock(); + RTM_NEWADDR, NLM_F_MULTI) <= 0) goto done; - } } - rcu_read_unlock(); } done: - read_unlock(&dev_base_lock); cb->args[0] = idx; cb->args[1] = ip_idx; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index eecba1886b49..1486f76f7878 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3224,7 +3224,6 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb, s_idx = cb->args[0]; s_ip_idx = ip_idx = cb->args[1]; - read_lock(&dev_base_lock); for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) { if (idx < s_idx) @@ -3286,7 +3285,6 @@ done: read_unlock_bh(&idev->lock); in6_dev_put(idev); } - read_unlock(&dev_base_lock); cb->args[0] = idx; cb->args[1] = ip_idx; return skb->len; -- cgit v1.2.3