From 31e6d363abcd0d05766c82f1a9c905a4c974a199 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 17 Jun 2009 19:05:41 -0700 Subject: net: correct off-by-one write allocations reports commit 2b85a34e911bf483c27cfdd124aeb1605145dc80 (net: No more expensive sock_hold()/sock_put() on each tx) changed initial sk_wmem_alloc value. We need to take into account this offset when reporting sk_wmem_alloc to user, in PROC_FS files or various ioctls (SIOCOUTQ/TIOCOUTQ) Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv6/raw.c | 7 ++++--- net/ipv6/udp.c | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'net/ipv6') diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 36a090d87a3..8b0b6f94806 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -1130,7 +1130,8 @@ static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg) switch(cmd) { case SIOCOUTQ: { - int amount = atomic_read(&sk->sk_wmem_alloc); + int amount = sk_wmem_alloc_get(sk); + return put_user(amount, (int __user *)arg); } case SIOCINQ: @@ -1236,8 +1237,8 @@ static void raw6_sock_seq_show(struct seq_file *seq, struct sock *sp, int i) dest->s6_addr32[0], dest->s6_addr32[1], dest->s6_addr32[2], dest->s6_addr32[3], destp, sp->sk_state, - atomic_read(&sp->sk_wmem_alloc), - atomic_read(&sp->sk_rmem_alloc), + sk_wmem_alloc_get(sp), + sk_rmem_alloc_get(sp), 0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp), diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index fc333d85472..023beda6b22 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -1061,8 +1061,8 @@ static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket dest->s6_addr32[0], dest->s6_addr32[1], dest->s6_addr32[2], dest->s6_addr32[3], destp, sp->sk_state, - atomic_read(&sp->sk_wmem_alloc), - atomic_read(&sp->sk_rmem_alloc), + sk_wmem_alloc_get(sp), + sk_rmem_alloc_get(sp), 0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp), -- cgit v1.2.3-70-g09d2 From d5fdd6babcfc2b0e6a8da1acf492a69fb54b4c47 Mon Sep 17 00:00:00 2001 From: Brian Haley Date: Tue, 23 Jun 2009 04:31:07 -0700 Subject: ipv6: Use correct data types for ICMPv6 type and code Change all the code that deals directly with ICMPv6 type and code values to use u8 instead of a signed int as that's the actual data type. Signed-off-by: Brian Haley Signed-off-by: David S. Miller --- include/linux/icmpv6.h | 6 +++--- include/net/protocol.h | 2 +- include/net/rawv6.h | 2 +- include/net/xfrm.h | 2 +- net/dccp/ipv6.c | 2 +- net/ipv6/ah6.c | 2 +- net/ipv6/esp6.c | 2 +- net/ipv6/icmp.c | 12 ++++++------ net/ipv6/ip6_tunnel.c | 18 +++++++++--------- net/ipv6/ipcomp6.c | 2 +- net/ipv6/mip6.c | 2 +- net/ipv6/raw.c | 4 ++-- net/ipv6/route.c | 2 +- net/ipv6/tcp_ipv6.c | 2 +- net/ipv6/tunnel6.c | 2 +- net/ipv6/udp.c | 6 +++--- net/ipv6/udp_impl.h | 2 +- net/ipv6/udplite.c | 2 +- net/ipv6/xfrm6_tunnel.c | 2 +- net/sctp/ipv6.c | 2 +- 20 files changed, 38 insertions(+), 38 deletions(-) (limited to 'net/ipv6') diff --git a/include/linux/icmpv6.h b/include/linux/icmpv6.h index 10d701eec48..b6a85183c33 100644 --- a/include/linux/icmpv6.h +++ b/include/linux/icmpv6.h @@ -175,16 +175,16 @@ struct icmp6_filter { extern void icmpv6_send(struct sk_buff *skb, - int type, int code, + u8 type, u8 code, __u32 info, struct net_device *dev); extern int icmpv6_init(void); -extern int icmpv6_err_convert(int type, int code, +extern int icmpv6_err_convert(u8 type, u8 code, int *err); extern void icmpv6_cleanup(void); extern void icmpv6_param_prob(struct sk_buff *skb, - int code, int pos); + u8 code, int pos); struct flowi; struct in6_addr; diff --git a/include/net/protocol.h b/include/net/protocol.h index ffa5b8b1f1d..1089d5aabd4 100644 --- a/include/net/protocol.h +++ b/include/net/protocol.h @@ -53,7 +53,7 @@ struct inet6_protocol void (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, + u8 type, u8 code, int offset, __be32 info); int (*gso_send_check)(struct sk_buff *skb); diff --git a/include/net/rawv6.h b/include/net/rawv6.h index 8a22599f26b..f6b9b830df8 100644 --- a/include/net/rawv6.h +++ b/include/net/rawv6.h @@ -6,7 +6,7 @@ #include void raw6_icmp_error(struct sk_buff *, int nexthdr, - int type, int code, int inner_offset, __be32); + u8 type, u8 code, int inner_offset, __be32); int raw6_local_deliver(struct sk_buff *, int); extern int rawv6_rcv(struct sock *sk, diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 736bca45088..9e3a3f4c1f6 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1274,7 +1274,7 @@ struct xfrm_tunnel { struct xfrm6_tunnel { int (*handler)(struct sk_buff *skb); int (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __be32 info); + u8 type, u8 code, int offset, __be32 info); struct xfrm6_tunnel *next; int priority; }; diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 05ea7440d9e..3e70faab298 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -85,7 +85,7 @@ static inline __u32 dccp_v6_init_sequence(struct sk_buff *skb) } static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __be32 info) + u8 type, u8 code, int offset, __be32 info) { struct ipv6hdr *hdr = (struct ipv6hdr *)skb->data; const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset); diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 52449f7a1b7..86f42a288c4 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -405,7 +405,7 @@ out: } static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __be32 info) + u8 type, u8 code, int offset, __be32 info) { struct net *net = dev_net(skb->dev); struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index c2f250150db..678bb95b152 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -354,7 +354,7 @@ static u32 esp6_get_mtu(struct xfrm_state *x, int mtu) } static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __be32 info) + u8 type, u8 code, int offset, __be32 info) { struct net *net = dev_net(skb->dev); struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 36dff880718..eab62a7a8f0 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -117,7 +117,7 @@ static __inline__ void icmpv6_xmit_unlock(struct sock *sk) /* * Slightly more convenient version of icmpv6_send. */ -void icmpv6_param_prob(struct sk_buff *skb, int code, int pos) +void icmpv6_param_prob(struct sk_buff *skb, u8 code, int pos) { icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos, skb->dev); kfree_skb(skb); @@ -161,7 +161,7 @@ static int is_ineligible(struct sk_buff *skb) /* * Check the ICMP output rate limit */ -static inline int icmpv6_xrlim_allow(struct sock *sk, int type, +static inline int icmpv6_xrlim_allow(struct sock *sk, u8 type, struct flowi *fl) { struct dst_entry *dst; @@ -305,7 +305,7 @@ static inline void mip6_addr_swap(struct sk_buff *skb) {} /* * Send an ICMP message in response to a packet in error */ -void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, +void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, struct net_device *dev) { struct net *net = dev_net(skb->dev); @@ -590,7 +590,7 @@ out: icmpv6_xmit_unlock(sk); } -static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) +static void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) { struct inet6_protocol *ipprot; int inner_offset; @@ -643,7 +643,7 @@ static int icmpv6_rcv(struct sk_buff *skb) struct in6_addr *saddr, *daddr; struct ipv6hdr *orig_hdr; struct icmp6hdr *hdr; - int type; + u8 type; if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { struct sec_path *sp = skb_sec_path(skb); @@ -914,7 +914,7 @@ static const struct icmp6_err { }, }; -int icmpv6_err_convert(int type, int code, int *err) +int icmpv6_err_convert(u8 type, u8 code, int *err) { int fatal = 0; diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 404d16a97d5..51f410e7775 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -394,13 +394,13 @@ parse_tlv_tnl_enc_lim(struct sk_buff *skb, __u8 * raw) static int ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt, - int *type, int *code, int *msg, __u32 *info, int offset) + u8 *type, u8 *code, int *msg, __u32 *info, int offset) { struct ipv6hdr *ipv6h = (struct ipv6hdr *) skb->data; struct ip6_tnl *t; int rel_msg = 0; - int rel_type = ICMPV6_DEST_UNREACH; - int rel_code = ICMPV6_ADDR_UNREACH; + u8 rel_type = ICMPV6_DEST_UNREACH; + u8 rel_code = ICMPV6_ADDR_UNREACH; __u32 rel_info = 0; __u16 len; int err = -ENOENT; @@ -488,11 +488,11 @@ out: static int ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __be32 info) + u8 type, u8 code, int offset, __be32 info) { int rel_msg = 0; - int rel_type = type; - int rel_code = code; + u8 rel_type = type; + u8 rel_code = code; __u32 rel_info = ntohl(info); int err; struct sk_buff *skb2; @@ -586,11 +586,11 @@ out: static int ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __be32 info) + u8 type, u8 code, int offset, __be32 info) { int rel_msg = 0; - int rel_type = type; - int rel_code = code; + u8 rel_type = type; + u8 rel_code = code; __u32 rel_info = ntohl(info); int err; diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 3a0b3be7ece..79c172f1ff0 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -51,7 +51,7 @@ #include static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __be32 info) + u8 type, u8 code, int offset, __be32 info) { __be32 spi; struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index f995e19c87a..f797e8c6f3b 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c @@ -54,7 +54,7 @@ static inline void *mip6_padn(__u8 *data, __u8 padlen) return data + padlen; } -static inline void mip6_param_prob(struct sk_buff *skb, int code, int pos) +static inline void mip6_param_prob(struct sk_buff *skb, u8 code, int pos) { icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos, skb->dev); } diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 8b0b6f94806..d6c3c1c34b2 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -310,7 +310,7 @@ out: static void rawv6_err(struct sock *sk, struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __be32 info) + u8 type, u8 code, int offset, __be32 info) { struct inet_sock *inet = inet_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk); @@ -343,7 +343,7 @@ static void rawv6_err(struct sock *sk, struct sk_buff *skb, } void raw6_icmp_error(struct sk_buff *skb, int nexthdr, - int type, int code, int inner_offset, __be32 info) + u8 type, u8 code, int inner_offset, __be32 info) { struct sock *sk; int hash; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 658293ea05b..1473ee0a1f5 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1865,7 +1865,7 @@ int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg) * Drop the packet on the floor */ -static int ip6_pkt_drop(struct sk_buff *skb, int code, int ipstats_mib_noroutes) +static int ip6_pkt_drop(struct sk_buff *skb, u8 code, int ipstats_mib_noroutes) { int type; struct dst_entry *dst = skb_dst(skb); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 53b6a4192b1..58810c65b63 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -317,7 +317,7 @@ failure: } static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __be32 info) + u8 type, u8 code, int offset, __be32 info) { struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; const struct tcphdr *th = (struct tcphdr *)(skb->data+offset); diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c index 669f280989c..633ad789eff 100644 --- a/net/ipv6/tunnel6.c +++ b/net/ipv6/tunnel6.c @@ -124,7 +124,7 @@ drop: } static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __be32 info) + u8 type, u8 code, int offset, __be32 info) { struct xfrm6_tunnel *handler; diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 023beda6b22..33b59bd92c4 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -312,7 +312,7 @@ csum_copy_err: } void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __be32 info, + u8 type, u8 code, int offset, __be32 info, struct udp_table *udptable) { struct ipv6_pinfo *np; @@ -346,8 +346,8 @@ out: } static __inline__ void udpv6_err(struct sk_buff *skb, - struct inet6_skb_parm *opt, int type, - int code, int offset, __be32 info ) + struct inet6_skb_parm *opt, u8 type, + u8 code, int offset, __be32 info ) { __udp6_lib_err(skb, opt, type, code, offset, info, &udp_table); } diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h index 23779208c33..6bb303471e2 100644 --- a/net/ipv6/udp_impl.h +++ b/net/ipv6/udp_impl.h @@ -9,7 +9,7 @@ extern int __udp6_lib_rcv(struct sk_buff *, struct udp_table *, int ); extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *, - int , int , int , __be32 , struct udp_table *); + u8 , u8 , int , __be32 , struct udp_table *); extern int udp_v6_get_port(struct sock *sk, unsigned short snum); diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c index ba162a82458..4818c48688f 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c @@ -20,7 +20,7 @@ static int udplitev6_rcv(struct sk_buff *skb) static void udplitev6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __be32 info) + u8 type, u8 code, int offset, __be32 info) { __udp6_lib_err(skb, opt, type, code, offset, info, &udplite_table); } diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 80193db224d..81a95c00e50 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -262,7 +262,7 @@ static int xfrm6_tunnel_rcv(struct sk_buff *skb) } static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __be32 info) + u8 type, u8 code, int offset, __be32 info) { /* xfrm6_tunnel native err handling */ switch (type) { diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index a63de3f7f18..6a4b1909414 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -133,7 +133,7 @@ static struct notifier_block sctp_inet6addr_notifier = { /* ICMP error handler. */ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __be32 info) + u8 type, u8 code, int offset, __be32 info) { struct inet6_dev *idev; struct sock *sk; -- cgit v1.2.3-70-g09d2 From a1faa69810b2af562b70b2a71c116c7d03575dd3 Mon Sep 17 00:00:00 2001 From: Jens Rosenboom Date: Thu, 25 Jun 2009 04:55:50 +0000 Subject: ipv6: avoid wraparound for expired preferred lifetime Avoid showing wrong high values when the preferred lifetime of an address is expired. Signed-off-by: Jens Rosenboom Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'net/ipv6') diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 8c1e86afbbf..3883b4036a7 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3362,7 +3362,10 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, valid = ifa->valid_lft; if (preferred != INFINITY_LIFE_TIME) { long tval = (jiffies - ifa->tstamp)/HZ; - preferred -= tval; + if (preferred > tval) + preferred -= tval; + else + preferred = 0; if (valid != INFINITY_LIFE_TIME) valid -= tval; } -- cgit v1.2.3-70-g09d2 From 1f2ccd00f224a4e2d6d26f590f3e6851f3deef99 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Fri, 26 Jun 2009 10:46:03 +0000 Subject: ipv6: Use rcu_barrier() on module unload. The ipv6 module uses rcu_call() thus it should use rcu_barrier() on module unload. Acked-by: Paul E. McKenney Signed-off-by: Jesper Dangaard Brouer Signed-off-by: David S. Miller --- net/ipv6/af_inet6.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'net/ipv6') diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 85b3d0036af..caa0278d30a 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -1284,6 +1284,8 @@ static void __exit inet6_exit(void) proto_unregister(&udplitev6_prot); proto_unregister(&udpv6_prot); proto_unregister(&tcpv6_prot); + + rcu_barrier(); /* Wait for completion of call_rcu()'s */ } module_exit(inet6_exit); -- cgit v1.2.3-70-g09d2 From 71f9dacd2e4d233029e9e956ca3f79531f411827 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 26 Jun 2009 19:22:37 -0700 Subject: inet: Call skb_orphan before tproxy activates As transparent proxying looks up the socket early and assigns it to the skb for later processing, we must drop any existing socket ownership prior to that in order to distinguish between the case where tproxy is active and where it is not. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv4/ip_input.c | 3 +++ net/ipv6/ip6_input.c | 3 +++ 2 files changed, 6 insertions(+) (limited to 'net/ipv6') diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 490ce20faf3..db46b4b5b2b 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -440,6 +440,9 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, /* Remove any debris in the socket control block */ memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); + /* Must drop socket now because of tproxy. */ + skb_orphan(skb); + return NF_HOOK(PF_INET, NF_INET_PRE_ROUTING, skb, dev, NULL, ip_rcv_finish); diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index c3a07d75b5f..6d6a4277c67 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -139,6 +139,9 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt rcu_read_unlock(); + /* Must drop socket now because of tproxy. */ + skb_orphan(skb); + return NF_HOOK(PF_INET6, NF_INET_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish); err: -- cgit v1.2.3-70-g09d2 From 59cae0092e4da753b5a2adb32933e0d1b223bcc5 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 2 Jul 2009 16:59:49 +0000 Subject: xfrm6: fix the proto and ports decode of sctp protocol The SCTP pushed the skb above the sctp chunk header, so the check of pskb_may_pull(skb, nh + offset + 1 - skb->data) in _decode_session6() will never return 0 and the ports decode of sctp will always fail. (nh + offset + 1 - skb->data < 0) Signed-off-by: Wei Yongjun Acked-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv6/xfrm6_policy.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'net/ipv6') diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index b4b16a43f27..3a3c677bc0f 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -157,7 +157,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) ipv6_addr_copy(&fl->fl6_dst, reverse ? &hdr->saddr : &hdr->daddr); ipv6_addr_copy(&fl->fl6_src, reverse ? &hdr->daddr : &hdr->saddr); - while (pskb_may_pull(skb, nh + offset + 1 - skb->data)) { + while (nh + offset + 1 < skb->data || + pskb_may_pull(skb, nh + offset + 1 - skb->data)) { nh = skb_network_header(skb); exthdr = (struct ipv6_opt_hdr *)(nh + offset); @@ -177,7 +178,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) case IPPROTO_TCP: case IPPROTO_SCTP: case IPPROTO_DCCP: - if (!onlyproto && pskb_may_pull(skb, nh + offset + 4 - skb->data)) { + if (!onlyproto && (nh + offset + 4 < skb->data || + pskb_may_pull(skb, nh + offset + 4 - skb->data))) { __be16 *ports = (__be16 *)exthdr; fl->fl_ip_sport = ports[!!reverse]; -- cgit v1.2.3-70-g09d2 From a1ed05263b74921742b454ef52c30b609ec6940f Mon Sep 17 00:00:00 2001 From: Brian Haley Date: Thu, 2 Jul 2009 07:10:52 +0000 Subject: IPv6: preferred lifetime of address not getting updated There's a bug in addrconf_prefix_rcv() where it won't update the preferred lifetime of an IPv6 address if the current valid lifetime of the address is less than 2 hours (the minimum value in the RA). For example, If I send a router advertisement with a prefix that has valid lifetime = preferred lifetime = 2 hours we'll build this address: 3: eth0: mtu 1500 qlen 1000 inet6 2001:1890:1109:a20:217:8ff:fe7d:4718/64 scope global dynamic valid_lft 7175sec preferred_lft 7175sec If I then send the same prefix with valid lifetime = preferred lifetime = 0 it will be ignored since the minimum valid lifetime is 2 hours: 3: eth0: mtu 1500 qlen 1000 inet6 2001:1890:1109:a20:217:8ff:fe7d:4718/64 scope global dynamic valid_lft 7161sec preferred_lft 7161sec But according to RFC 4862 we should always reset the preferred lifetime even if the valid lifetime is invalid, which would cause the address to immediately get deprecated. So with this patch we'd see this: 5: eth0: mtu 1500 qlen 1000 inet6 2001:1890:1109:a20:21f:29ff:fe5a:ef04/64 scope global deprecated dynamic valid_lft 7163sec preferred_lft 0sec The comment winds-up being 5x the size of the code to fix the problem. Update the preferred lifetime of IPv6 addresses derived from a prefix info option in a router advertisement even if the valid lifetime in the option is invalid, as specified in RFC 4862 Section 5.5.3e. Fixes an issue where an address will not immediately become deprecated. Reported by Jens Rosenboom. Signed-off-by: Brian Haley Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) (limited to 'net/ipv6') diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 3883b4036a7..43b3c9f89c1 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1916,8 +1916,32 @@ ok: update_lft = 1; else if (stored_lft <= MIN_VALID_LIFETIME) { /* valid_lft <= stored_lft is always true */ - /* XXX: IPsec */ - update_lft = 0; + /* + * RFC 4862 Section 5.5.3e: + * "Note that the preferred lifetime of + * the corresponding address is always + * reset to the Preferred Lifetime in + * the received Prefix Information + * option, regardless of whether the + * valid lifetime is also reset or + * ignored." + * + * So if the preferred lifetime in + * this advertisement is different + * than what we have stored, but the + * valid lifetime is invalid, just + * reset prefered_lft. + * + * We must set the valid lifetime + * to the stored lifetime since we'll + * be updating the timestamp below, + * else we'll set it back to the + * minumum. + */ + if (prefered_lft != ifp->prefered_lft) { + valid_lft = stored_lft; + update_lft = 1; + } } else { valid_lft = MIN_VALID_LIFETIME; if (valid_lft < prefered_lft) @@ -3085,7 +3109,7 @@ restart: spin_unlock(&ifp->lock); continue; } else if (age >= ifp->prefered_lft) { - /* jiffies - ifp->tsamp > age >= ifp->prefered_lft */ + /* jiffies - ifp->tstamp > age >= ifp->prefered_lft */ int deprecate = 0; if (!(ifp->flags&IFA_F_DEPRECATED)) { -- cgit v1.2.3-70-g09d2 From e51a67a9c8a2ea5c563f8c2ba6613fe2100ffe67 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 8 Jul 2009 14:20:42 +0000 Subject: net: ip_push_pending_frames() fix After commit 2b85a34e911bf483c27cfdd124aeb1605145dc80 (net: No more expensive sock_hold()/sock_put() on each tx) we do not take any more references on sk->sk_refcnt on outgoing packets. I forgot to delete two __sock_put() from ip_push_pending_frames() and ip6_push_pending_frames(). Reported-by: Emil S Tantilov Signed-off-by: Eric Dumazet Tested-by: Emil S Tantilov Signed-off-by: David S. Miller --- net/ipv4/ip_output.c | 1 - net/ipv6/ip6_output.c | 1 - 2 files changed, 2 deletions(-) (limited to 'net/ipv6') diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 24702628266..7d082105472 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1243,7 +1243,6 @@ int ip_push_pending_frames(struct sock *sk) skb->len += tmp_skb->len; skb->data_len += tmp_skb->len; skb->truesize += tmp_skb->truesize; - __sock_put(tmp_skb->sk); tmp_skb->destructor = NULL; tmp_skb->sk = NULL; } diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 7c76e3d1821..87f8419a68f 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1484,7 +1484,6 @@ int ip6_push_pending_frames(struct sock *sk) skb->len += tmp_skb->len; skb->data_len += tmp_skb->len; skb->truesize += tmp_skb->truesize; - __sock_put(tmp_skb->sk); tmp_skb->destructor = NULL; tmp_skb->sk = NULL; } -- cgit v1.2.3-70-g09d2 From f2ba025b2036e52a176cddcf91b15ac2b10c644a Mon Sep 17 00:00:00 2001 From: Sascha Hlusiak Date: Sat, 11 Jul 2009 20:30:52 -0700 Subject: sit: fix regression: do not release skb->dst before xmit The sit module makes use of skb->dst in it's xmit function, so since 93f154b594fe47 ("net: release dst entry in dev_hard_start_xmit()") sit tunnels are broken, because the flag IFF_XMIT_DST_RELEASE is not unset. This patch unsets that flag for sit devices to fix this regression. Signed-off-by: Sascha Hlusiak Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv6/sit.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net/ipv6') diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 68e52308e55..98b7327d094 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -1018,6 +1018,7 @@ static void ipip6_tunnel_setup(struct net_device *dev) dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr); dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr); dev->flags = IFF_NOARP; + dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; dev->iflink = 0; dev->addr_len = 4; dev->features |= NETIF_F_NETNS_LOCAL; -- cgit v1.2.3-70-g09d2 From e3afe7b75ed8f809c1473ea9b39267487c187ccb Mon Sep 17 00:00:00 2001 From: John Dykstra Date: Thu, 16 Jul 2009 05:04:51 +0000 Subject: tcp: Fix MD5 signature checking on IPv4 mapped sockets Fix MD5 signature checking so that an IPv4 active open to an IPv6 socket can succeed. In particular, use the correct address family's signature generation function for the SYN/ACK. Reported-by: Stephen Hemminger Signed-off-by: John Dykstra Signed-off-by: David S. Miller --- include/net/tcp.h | 5 +++++ net/ipv4/tcp_ipv4.c | 1 + net/ipv4/tcp_output.c | 2 +- net/ipv6/tcp_ipv6.c | 1 + 4 files changed, 8 insertions(+), 1 deletion(-) (limited to 'net/ipv6') diff --git a/include/net/tcp.h b/include/net/tcp.h index 19f4150f4d4..88af8430647 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1425,6 +1425,11 @@ struct tcp_request_sock_ops { #ifdef CONFIG_TCP_MD5SIG struct tcp_md5sig_key *(*md5_lookup) (struct sock *sk, struct request_sock *req); + int (*calc_md5_hash) (char *location, + struct tcp_md5sig_key *md5, + struct sock *sk, + struct request_sock *req, + struct sk_buff *skb); #endif }; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 5a1ca2698c8..7c107eb876c 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1160,6 +1160,7 @@ struct request_sock_ops tcp_request_sock_ops __read_mostly = { #ifdef CONFIG_TCP_MD5SIG static struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { .md5_lookup = tcp_v4_reqsk_md5_lookup, + .calc_md5_hash = tcp_v4_md5_hash_skb, }; #endif diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 5bdf08d312d..bd62712848f 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2261,7 +2261,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, #ifdef CONFIG_TCP_MD5SIG /* Okay, we have all we need - do the md5 hash if needed */ if (md5) { - tp->af_specific->calc_md5_hash(md5_hash_location, + tcp_rsk(req)->af_specific->calc_md5_hash(md5_hash_location, md5, NULL, req, skb); } #endif diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 58810c65b63..ae3d6575356 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -896,6 +896,7 @@ struct request_sock_ops tcp6_request_sock_ops __read_mostly = { #ifdef CONFIG_TCP_MD5SIG static struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { .md5_lookup = tcp_v6_reqsk_md5_lookup, + .calc_md5_hash = tcp_v6_md5_hash_skb, }; #endif -- cgit v1.2.3-70-g09d2 From e547bc1eccf539b7403138d8ded913ffd2b7fd0d Mon Sep 17 00:00:00 2001 From: John Dykstra Date: Fri, 17 Jul 2009 09:23:22 +0000 Subject: tcp: Use correct peer adr when copying MD5 keys When the TCP connection handshake completes on the passive side, a variety of state must be set up in the "child" sock, including the key if MD5 authentication is being used. Fix TCP for both address families to label the key with the peer's destination address, rather than the address from the listening sock, which is usually the wildcard. Reported-by: Stephen Hemminger Signed-off-by: John Dykstra Signed-off-by: David S. Miller --- net/ipv4/tcp_ipv4.c | 2 +- net/ipv6/tcp_ipv6.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'net/ipv6') diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 7c107eb876c..6d88219c5e2 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1374,7 +1374,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, */ char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC); if (newkey != NULL) - tcp_v4_md5_do_add(newsk, inet_sk(sk)->daddr, + tcp_v4_md5_do_add(newsk, newinet->daddr, newkey, key->keylen); newsk->sk_route_caps &= ~NETIF_F_GSO_MASK; } diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index ae3d6575356..d849dd53b78 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1442,7 +1442,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, */ char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC); if (newkey != NULL) - tcp_v6_md5_do_add(newsk, &inet6_sk(sk)->daddr, + tcp_v6_md5_do_add(newsk, &newnp->daddr, newkey, key->keylen); } #endif -- cgit v1.2.3-70-g09d2 From ca6982b858e1d08010c1d29d8e8255b2ac2ad70a Mon Sep 17 00:00:00 2001 From: Bruno Prémont Date: Sun, 23 Aug 2009 19:06:28 -0700 Subject: ipv6: Fix commit 63d9950b08184e6531adceb65f64b429909cc101 (ipv6: Make v4-mapped bindings consistent with IPv4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 63d9950b08184e6531adceb65f64b429909cc101 (ipv6: Make v4-mapped bindings consistent with IPv4) changes behavior of inet6_bind() for v4-mapped addresses so it should behave the same way as inet_bind(). During this change setting of err to -EADDRNOTAVAIL got lost: af_inet.c:469 inet_bind() err = -EADDRNOTAVAIL; if (!sysctl_ip_nonlocal_bind && !(inet->freebind || inet->transparent) && addr->sin_addr.s_addr != htonl(INADDR_ANY) && chk_addr_ret != RTN_LOCAL && chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST) goto out; af_inet6.c:463 inet6_bind() if (addr_type == IPV6_ADDR_MAPPED) { int chk_addr_ret; /* Binding to v4-mapped address on a v6-only socket * makes no sense */ if (np->ipv6only) { err = -EINVAL; goto out; } /* Reproduce AF_INET checks to make the bindings consitant */ v4addr = addr->sin6_addr.s6_addr32[3]; chk_addr_ret = inet_addr_type(net, v4addr); if (!sysctl_ip_nonlocal_bind && !(inet->freebind || inet->transparent) && v4addr != htonl(INADDR_ANY) && chk_addr_ret != RTN_LOCAL && chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST) goto out; } else { Signed-off-by Bruno Prémont Signed-off-by: David S. Miller --- net/ipv6/af_inet6.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'net/ipv6') diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index caa0278d30a..45f9a2a42d5 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -306,8 +306,10 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) v4addr != htonl(INADDR_ANY) && chk_addr_ret != RTN_LOCAL && chk_addr_ret != RTN_MULTICAST && - chk_addr_ret != RTN_BROADCAST) + chk_addr_ret != RTN_BROADCAST) { + err = -EADDRNOTAVAIL; goto out; + } } else { if (addr_type != IPV6_ADDR_ANY) { struct net_device *dev = NULL; -- cgit v1.2.3-70-g09d2