diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 31 | ||||
-rw-r--r-- | net/ipv6/anycast.c | 9 | ||||
-rw-r--r-- | net/ipv6/esp6.c | 2 | ||||
-rw-r--r-- | net/ipv6/icmp.c | 22 | ||||
-rw-r--r-- | net/ipv6/ip6_input.c | 3 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 22 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_queue.c | 8 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_reasm.c | 2 | ||||
-rw-r--r-- | net/ipv6/xfrm6_mode_beet.c | 1 | ||||
-rw-r--r-- | net/ipv6/xfrm6_mode_tunnel.c | 2 | ||||
-rw-r--r-- | net/ipv6/xfrm6_output.c | 2 | ||||
-rw-r--r-- | net/ipv6/xfrm6_state.c | 2 |
12 files changed, 69 insertions, 37 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 101e0e70ba2..a65935a9afd 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -776,6 +776,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i struct inet6_dev *idev = ifp->idev; struct in6_addr addr, *tmpaddr; unsigned long tmp_prefered_lft, tmp_valid_lft, tmp_cstamp, tmp_tstamp; + unsigned long regen_advance; int tmp_plen; int ret = 0; int max_addresses; @@ -836,8 +837,23 @@ retry: tmp_tstamp = ifp->tstamp; spin_unlock_bh(&ifp->lock); + regen_advance = idev->cnf.regen_max_retry * + idev->cnf.dad_transmits * + idev->nd_parms->retrans_time / HZ; write_unlock(&idev->lock); + /* A temporary address is created only if this calculated Preferred + * Lifetime is greater than REGEN_ADVANCE time units. In particular, + * an implementation must not create a temporary address with a zero + * Preferred Lifetime. + */ + if (tmp_prefered_lft <= regen_advance) { + in6_ifa_put(ifp); + in6_dev_put(idev); + ret = -1; + goto out; + } + addr_flags = IFA_F_TEMPORARY; /* set in addrconf_prefix_rcv() */ if (ifp->flags & IFA_F_OPTIMISTIC) @@ -1831,6 +1847,9 @@ ok: * lifetimes of an existing temporary address * when processing a Prefix Information Option. */ + if (ifp != ift->ifpub) + continue; + spin_lock(&ift->lock); flags = ift->flags; if (ift->valid_lft > valid_lft && @@ -2437,7 +2456,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) ASSERT_RTNL(); - if (dev == init_net.loopback_dev && how == 1) + if ((dev->flags & IFF_LOOPBACK) && how == 1) how = 0; rt6_ifdown(dev); @@ -2450,7 +2469,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) /* Step 1: remove reference to ipv6 device from parent device. Do not dev_put! */ - if (how == 1) { + if (how) { idev->dead = 1; /* protected by rtnl_lock */ @@ -2482,12 +2501,12 @@ static int addrconf_ifdown(struct net_device *dev, int how) write_lock_bh(&idev->lock); /* Step 3: clear flags for stateless addrconf */ - if (how != 1) + if (!how) idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY); /* Step 4: clear address list */ #ifdef CONFIG_IPV6_PRIVACY - if (how == 1 && del_timer(&idev->regen_timer)) + if (how && del_timer(&idev->regen_timer)) in6_dev_put(idev); /* clear tempaddr list */ @@ -2524,7 +2543,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) /* Step 5: Discard multicast list */ - if (how == 1) + if (how) ipv6_mc_destroy_dev(idev); else ipv6_mc_down(idev); @@ -2533,7 +2552,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) /* Shot the device (if unregistered) */ - if (how == 1) { + if (how) { addrconf_sysctl_unregister(idev); neigh_parms_release(&nd_tbl, idev->nd_parms); neigh_ifdown(&nd_tbl, dev); diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index 9c7f83fbc3a..e5f56c953b5 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c @@ -334,9 +334,7 @@ int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr) idev->ac_list = aca; write_unlock_bh(&idev->lock); - dst_hold(&rt->u.dst); - if (ip6_ins_rt(rt)) - dst_release(&rt->u.dst); + ip6_ins_rt(rt); addrconf_join_solict(dev, &aca->aca_addr); @@ -378,10 +376,7 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr) addrconf_leave_solict(idev, &aca->aca_addr); dst_hold(&aca->aca_rt->u.dst); - if (ip6_del_rt(aca->aca_rt)) - dst_free(&aca->aca_rt->u.dst); - else - dst_release(&aca->aca_rt->u.dst); + ip6_del_rt(aca->aca_rt); aca_put(aca); return 0; diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 0ec1402320e..c6bb4c6d24b 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -282,7 +282,7 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) struct scatterlist *sg; struct scatterlist *asg; - if (!pskb_may_pull(skb, sizeof(*esph))) { + if (!pskb_may_pull(skb, sizeof(*esph) + crypto_aead_ivsize(aead))) { ret = -EINVAL; goto out; } diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 121d517bf91..893287ecc62 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -436,24 +436,26 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, } if (xfrm_decode_session_reverse(skb, &fl2, AF_INET6)) - goto out; + goto relookup_failed; if (ip6_dst_lookup(sk, &dst2, &fl)) - goto out; + goto relookup_failed; err = xfrm_lookup(&dst2, &fl, sk, XFRM_LOOKUP_ICMP); - if (err == -ENOENT) { + switch (err) { + case 0: + dst_release(dst); + dst = dst2; + break; + case -EPERM: + goto out_dst_release; + default: +relookup_failed: if (!dst) goto out; - goto route_done; + break; } - dst_release(dst); - dst = dst2; - - if (err) - goto out; - route_done: if (ipv6_addr_is_multicast(&fl.fl6_dst)) hlimit = np->mcast_hops; diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 178aebc0427..98ab4f45990 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -239,8 +239,7 @@ int ip6_mc_input(struct sk_buff *skb) IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCASTPKTS); hdr = ipv6_hdr(skb); - deliver = unlikely(skb->dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) || - ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL); + deliver = ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL); /* * IPv6 multicast router mode isnt currently supported. diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 51557c27a0c..452a2ac4eec 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -676,6 +676,20 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb) } } +static struct pneigh_entry *pndisc_check_router(struct net_device *dev, + struct in6_addr *addr, int *is_router) +{ + struct pneigh_entry *n; + + read_lock_bh(&nd_tbl.lock); + n = __pneigh_lookup(&nd_tbl, &init_net, addr, dev); + if (n != NULL) + *is_router = (n->flags & NTF_ROUTER); + read_unlock_bh(&nd_tbl.lock); + + return n; +} + static void ndisc_recv_ns(struct sk_buff *skb) { struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); @@ -692,7 +706,7 @@ static void ndisc_recv_ns(struct sk_buff *skb) struct pneigh_entry *pneigh = NULL; int dad = ipv6_addr_any(saddr); int inc; - int is_router; + int is_router = 0; if (ipv6_addr_is_multicast(&msg->target)) { ND_PRINTK2(KERN_WARNING @@ -790,8 +804,8 @@ static void ndisc_recv_ns(struct sk_buff *skb) if (ipv6_chk_acast_addr(dev, &msg->target) || (idev->cnf.forwarding && (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) && - (pneigh = pneigh_lookup(&nd_tbl, &init_net, - &msg->target, dev, 0)) != NULL)) { + (pneigh = pndisc_check_router(dev, &msg->target, + &is_router)) != NULL)) { if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) && skb->pkt_type != PACKET_HOST && inc != 0 && @@ -812,7 +826,7 @@ static void ndisc_recv_ns(struct sk_buff *skb) goto out; } - is_router = !!(pneigh ? pneigh->flags & NTF_ROUTER : idev->cnf.forwarding); + is_router = !!(pneigh ? is_router : idev->cnf.forwarding); if (dad) { struct in6_addr maddr; diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index cc2f9afcf80..8d366f7f2a9 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -591,11 +591,9 @@ static int __init ip6_queue_init(void) } #ifdef CONFIG_PROC_FS - proc = create_proc_entry(IPQ_PROC_FS_NAME, 0, init_net.proc_net); - if (proc) { - proc->owner = THIS_MODULE; - proc->proc_fops = &ip6_queue_proc_fops; - } else { + proc = proc_create(IPQ_PROC_FS_NAME, 0, init_net.proc_net, + &ip6_queue_proc_fops); + if (!proc) { printk(KERN_ERR "ip6_queue: failed to create proc entry\n"); goto cleanup_ipqnl; } diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 2a0d698b24d..24c0d03095b 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -171,7 +171,9 @@ static __inline__ void fq_kill(struct nf_ct_frag6_queue *fq) static void nf_ct_frag6_evictor(void) { + local_bh_disable(); inet_frag_evictor(&nf_init_frags, &nf_frags); + local_bh_enable(); } static void nf_ct_frag6_expire(unsigned long data) diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c index 0527d11c1ae..d6ce400f585 100644 --- a/net/ipv6/xfrm6_mode_beet.c +++ b/net/ipv6/xfrm6_mode_beet.c @@ -45,6 +45,7 @@ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) skb->mac_header = skb->network_header + offsetof(struct ipv6hdr, nexthdr); skb->transport_header = skb->network_header + sizeof(*top_iph); + __skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl); xfrm6_beet_make_header(skb); diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c index 0c742faaa30..e20529b4c82 100644 --- a/net/ipv6/xfrm6_mode_tunnel.c +++ b/net/ipv6/xfrm6_mode_tunnel.c @@ -45,7 +45,7 @@ static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) memcpy(top_iph->flow_lbl, XFRM_MODE_SKB_CB(skb)->flow_lbl, sizeof(top_iph->flow_lbl)); - top_iph->nexthdr = x->inner_mode->afinfo->proto; + top_iph->nexthdr = xfrm_af2proto(skb->dst->ops->family); dsfield = XFRM_MODE_SKB_CB(skb)->tos; dsfield = INET_ECN_encapsulate(dsfield, dsfield); diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 79ccfb08073..0af823cf7f1 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c @@ -62,7 +62,7 @@ int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb) { int err; - err = x->inner_mode->afinfo->extract_output(x, skb); + err = xfrm_inner_extract_output(x, skb); if (err) return err; diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index dc817e035e2..ff1e1db8e23 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c @@ -174,10 +174,12 @@ int xfrm6_extract_header(struct sk_buff *skb) { struct ipv6hdr *iph = ipv6_hdr(skb); + XFRM_MODE_SKB_CB(skb)->ihl = sizeof(*iph); XFRM_MODE_SKB_CB(skb)->id = 0; XFRM_MODE_SKB_CB(skb)->frag_off = htons(IP_DF); XFRM_MODE_SKB_CB(skb)->tos = ipv6_get_dsfield(iph); XFRM_MODE_SKB_CB(skb)->ttl = iph->hop_limit; + XFRM_MODE_SKB_CB(skb)->optlen = 0; memcpy(XFRM_MODE_SKB_CB(skb)->flow_lbl, iph->flow_lbl, sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl)); |