diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/af_inet6.c | 4 | ||||
-rw-r--r-- | net/ipv6/icmp.c | 17 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 18 | ||||
-rw-r--r-- | net/ipv6/ip6_tunnel.c | 2 | ||||
-rw-r--r-- | net/ipv6/ip6mr.c | 9 | ||||
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 5 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 24 | ||||
-rw-r--r-- | net/ipv6/protocol.c | 15 | ||||
-rw-r--r-- | net/ipv6/raw.c | 9 | ||||
-rw-r--r-- | net/ipv6/route.c | 34 | ||||
-rw-r--r-- | net/ipv6/sit.c | 5 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 21 | ||||
-rw-r--r-- | net/ipv6/udp.c | 17 |
13 files changed, 79 insertions, 101 deletions
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index bf85d5f97032..a123a328aeb3 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; diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index eab62a7a8f06..e2325f6a05fb 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -323,7 +323,7 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, int iif = 0; int addr_type = 0; int len; - int hlimit, tclass; + int hlimit; int err = 0; if ((u8 *)hdr < skb->head || @@ -469,10 +469,6 @@ route_done: if (hlimit < 0) hlimit = ip6_dst_hoplimit(dst); - tclass = np->tclass; - if (tclass < 0) - tclass = 0; - msg.skb = skb; msg.offset = skb_network_offset(skb); msg.type = type; @@ -488,8 +484,8 @@ route_done: err = ip6_append_data(sk, icmpv6_getfrag, &msg, len + sizeof(struct icmp6hdr), - sizeof(struct icmp6hdr), - hlimit, tclass, NULL, &fl, (struct rt6_info*)dst, + sizeof(struct icmp6hdr), hlimit, + np->tclass, NULL, &fl, (struct rt6_info*)dst, MSG_DONTWAIT); if (err) { ip6_flush_pending_frames(sk); @@ -522,7 +518,6 @@ static void icmpv6_echo_reply(struct sk_buff *skb) struct dst_entry *dst; int err = 0; int hlimit; - int tclass; saddr = &ipv6_hdr(skb)->daddr; @@ -562,10 +557,6 @@ static void icmpv6_echo_reply(struct sk_buff *skb) if (hlimit < 0) hlimit = ip6_dst_hoplimit(dst); - tclass = np->tclass; - if (tclass < 0) - tclass = 0; - idev = in6_dev_get(skb->dev); msg.skb = skb; @@ -573,7 +564,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) msg.type = ICMPV6_ECHO_REPLY; err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr), - sizeof(struct icmp6hdr), hlimit, tclass, NULL, &fl, + sizeof(struct icmp6hdr), hlimit, np->tclass, NULL, &fl, (struct rt6_info*)dst, MSG_DONTWAIT); if (err) { diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 93beee944657..cd48801a8d6f 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -194,7 +194,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, struct ipv6hdr *hdr; u8 proto = fl->proto; int seg_len = skb->len; - int hlimit, tclass; + int hlimit = -1; + int tclass = 0; u32 mtu; if (opt) { @@ -237,19 +238,13 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, /* * Fill in the IPv6 header */ - - hlimit = -1; - if (np) + if (np) { + tclass = np->tclass; hlimit = np->hop_limit; + } if (hlimit < 0) hlimit = ip6_dst_hoplimit(dst); - tclass = -1; - if (np) - tclass = np->tclass; - if (tclass < 0) - tclass = 0; - *(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl->fl6_flowlabel; hdr->payload_len = htons(seg_len); @@ -1516,7 +1511,7 @@ int ip6_push_pending_frames(struct sock *sk) err = ip6_local_out(skb); if (err) { if (err > 0) - err = np->recverr ? net_xmit_errno(err) : 0; + err = net_xmit_errno(err); if (err) goto error; } @@ -1525,6 +1520,7 @@ out: ip6_cork_release(inet, np); return err; error: + IP6_INC_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS); goto out; } diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index a1d6045c4694..7d25bbe32110 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -1036,7 +1036,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } -static int +static netdev_tx_t ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) { struct ip6_tnl *t = netdev_priv(dev); diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 07ded5075b33..5c8d73730c75 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -204,7 +204,7 @@ static int ip6mr_vif_seq_show(struct seq_file *seq, void *v) return 0; } -static struct seq_operations ip6mr_vif_seq_ops = { +static const struct seq_operations ip6mr_vif_seq_ops = { .start = ip6mr_vif_seq_start, .next = ip6mr_vif_seq_next, .stop = ip6mr_vif_seq_stop, @@ -217,7 +217,7 @@ static int ip6mr_vif_open(struct inode *inode, struct file *file) sizeof(struct ipmr_vif_iter)); } -static struct file_operations ip6mr_vif_fops = { +static const struct file_operations ip6mr_vif_fops = { .owner = THIS_MODULE, .open = ip6mr_vif_open, .read = seq_read, @@ -341,7 +341,7 @@ static int ipmr_mfc_open(struct inode *inode, struct file *file) sizeof(struct ipmr_mfc_iter)); } -static struct file_operations ip6mr_mfc_fops = { +static const struct file_operations ip6mr_mfc_fops = { .owner = THIS_MODULE, .open = ipmr_mfc_open, .read = seq_read, @@ -416,7 +416,8 @@ static struct inet6_protocol pim6_protocol = { /* Service routines creating virtual interfaces: PIMREG */ -static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, + struct net_device *dev) { struct net *net = dev_net(dev); diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index a7fdf9a27f15..f5e0682b402d 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -315,6 +315,9 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, goto e_inval; if (val < -1 || val > 0xff) goto e_inval; + /* RFC 3542, 6.5: default traffic class of 0x0 */ + if (val == -1) + val = 0; np->tclass = val; retv = 0; break; @@ -1037,8 +1040,6 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, case IPV6_TCLASS: val = np->tclass; - if (val < 0) - val = 0; break; case IPV6_RECVTCLASS: diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 9eb68e92cc18..7015478797f6 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -98,7 +98,7 @@ static int pndisc_constructor(struct pneigh_entry *n); static void pndisc_destructor(struct pneigh_entry *n); static void pndisc_redo(struct sk_buff *skb); -static struct neigh_ops ndisc_generic_ops = { +static const struct neigh_ops ndisc_generic_ops = { .family = AF_INET6, .solicit = ndisc_solicit, .error_report = ndisc_error_report, @@ -108,7 +108,7 @@ static struct neigh_ops ndisc_generic_ops = { .queue_xmit = dev_queue_xmit, }; -static struct neigh_ops ndisc_hh_ops = { +static const struct neigh_ops ndisc_hh_ops = { .family = AF_INET6, .solicit = ndisc_solicit, .error_report = ndisc_error_report, @@ -119,7 +119,7 @@ static struct neigh_ops ndisc_hh_ops = { }; -static struct neigh_ops ndisc_direct_ops = { +static const struct neigh_ops ndisc_direct_ops = { .family = AF_INET6, .output = dev_queue_xmit, .connected_output = dev_queue_xmit, @@ -955,8 +955,8 @@ static void ndisc_recv_na(struct sk_buff *skb) */ if (skb->pkt_type != PACKET_LOOPBACK) ND_PRINTK1(KERN_WARNING - "ICMPv6 NA: someone advertises our address on %s!\n", - ifp->idev->dev->name); + "ICMPv6 NA: someone advertises our address %pI6 on %s!\n", + &ifp->addr, ifp->idev->dev->name); in6_ifa_put(ifp); return; } @@ -1151,10 +1151,6 @@ static void ndisc_router_discovery(struct sk_buff *skb) skb->dev->name); return; } - if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) { - in6_dev_put(in6_dev); - return; - } if (!ndisc_parse_options(opt, optlen, &ndopts)) { in6_dev_put(in6_dev); @@ -1163,6 +1159,10 @@ static void ndisc_router_discovery(struct sk_buff *skb) return; } + /* skip route and link configuration on routers */ + if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) + goto skip_linkparms; + #ifdef CONFIG_IPV6_NDISC_NODETYPE /* skip link-specific parameters from interior routers */ if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT) @@ -1283,9 +1283,7 @@ skip_defrtr: } } -#ifdef CONFIG_IPV6_NDISC_NODETYPE skip_linkparms: -#endif /* * Process options. @@ -1312,6 +1310,10 @@ skip_linkparms: NEIGH_UPDATE_F_ISROUTER); } + /* skip route and link configuration on routers */ + if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) + goto out; + #ifdef CONFIG_IPV6_ROUTE_INFO if (in6_dev->cnf.accept_ra_rtr_pref && ndopts.nd_opts_ri) { struct nd_opt_hdr *p; diff --git a/net/ipv6/protocol.c b/net/ipv6/protocol.c index 9ab789159913..568864f722ca 100644 --- a/net/ipv6/protocol.c +++ b/net/ipv6/protocol.c @@ -20,20 +20,9 @@ * - Removed unused variable 'inet6_protocol_base' * - Modified inet6_del_protocol() to correctly maintain copy bit. */ - -#include <linux/errno.h> -#include <linux/types.h> -#include <linux/socket.h> -#include <linux/sockios.h> -#include <linux/net.h> -#include <linux/in6.h> +#include <linux/module.h> #include <linux/netdevice.h> -#include <linux/if_arp.h> - -#include <net/sock.h> -#include <net/snmp.h> - -#include <net/ipv6.h> +#include <linux/spinlock.h> #include <net/protocol.h> struct inet6_protocol *inet6_protos[MAX_INET_PROTOS]; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index d6c3c1c34b2d..7d675b8d82d3 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -642,7 +642,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev, dst_output); if (err > 0) - err = np->recverr ? net_xmit_errno(err) : 0; + err = net_xmit_errno(err); if (err) goto error; out: @@ -653,6 +653,8 @@ error_fault: kfree_skb(skb); error: IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS); + if (err == -ENOBUFS && !np->recverr) + err = 0; return err; } @@ -877,11 +879,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, hlimit = ip6_dst_hoplimit(dst); } - if (tclass < 0) { + if (tclass < 0) tclass = np->tclass; - if (tclass < 0) - tclass = 0; - } if (msg->msg_flags&MSG_CONFIRM) goto do_confirm; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 1473ee0a1f51..9ccfef345560 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -665,7 +665,7 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *dad net->ipv6.sysctl.ip6_rt_gc_elasticity = 1; net->ipv6.sysctl.ip6_rt_gc_min_interval = 0; - ip6_dst_gc(net->ipv6.ip6_dst_ops); + ip6_dst_gc(&net->ipv6.ip6_dst_ops); net->ipv6.sysctl.ip6_rt_gc_elasticity = saved_rt_elasticity; @@ -970,7 +970,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, if (unlikely(idev == NULL)) return NULL; - rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); + rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops); if (unlikely(rt == NULL)) { in6_dev_put(idev); goto out; @@ -1060,7 +1060,7 @@ static void icmp6_clean_all(int (*func)(struct rt6_info *rt, void *arg), static int ip6_dst_gc(struct dst_ops *ops) { unsigned long now = jiffies; - struct net *net = ops->dst_net; + struct net *net = container_of(ops, struct net, ipv6.ip6_dst_ops); int rt_min_interval = net->ipv6.sysctl.ip6_rt_gc_min_interval; int rt_max_size = net->ipv6.sysctl.ip6_rt_max_size; int rt_elasticity = net->ipv6.sysctl.ip6_rt_gc_elasticity; @@ -1154,7 +1154,7 @@ int ip6_route_add(struct fib6_config *cfg) goto out; } - rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); + rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops); if (rt == NULL) { err = -ENOMEM; @@ -1643,7 +1643,7 @@ out: static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) { struct net *net = dev_net(ort->rt6i_dev); - struct rt6_info *rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); + struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops); if (rt) { rt->u.dst.input = ort->u.dst.input; @@ -1923,7 +1923,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, int anycast) { struct net *net = dev_net(idev->dev); - struct rt6_info *rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); + struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops); struct neighbour *neigh; if (rt == NULL) @@ -2501,7 +2501,7 @@ static int rt6_stats_seq_show(struct seq_file *seq, void *v) net->ipv6.rt6_stats->fib_rt_alloc, net->ipv6.rt6_stats->fib_rt_entries, net->ipv6.rt6_stats->fib_rt_cache, - atomic_read(&net->ipv6.ip6_dst_ops->entries), + atomic_read(&net->ipv6.ip6_dst_ops.entries), net->ipv6.rt6_stats->fib_discarded_routes); return 0; @@ -2637,7 +2637,7 @@ struct ctl_table *ipv6_route_sysctl_init(struct net *net) if (table) { table[0].data = &net->ipv6.sysctl.flush_delay; - table[1].data = &net->ipv6.ip6_dst_ops->gc_thresh; + table[1].data = &net->ipv6.ip6_dst_ops.gc_thresh; table[2].data = &net->ipv6.sysctl.ip6_rt_max_size; table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval; table[4].data = &net->ipv6.sysctl.ip6_rt_gc_timeout; @@ -2655,12 +2655,8 @@ static int ip6_route_net_init(struct net *net) { int ret = -ENOMEM; - net->ipv6.ip6_dst_ops = kmemdup(&ip6_dst_ops_template, - sizeof(*net->ipv6.ip6_dst_ops), - GFP_KERNEL); - if (!net->ipv6.ip6_dst_ops) - goto out; - net->ipv6.ip6_dst_ops->dst_net = hold_net(net); + memcpy(&net->ipv6.ip6_dst_ops, &ip6_dst_ops_template, + sizeof(net->ipv6.ip6_dst_ops)); net->ipv6.ip6_null_entry = kmemdup(&ip6_null_entry_template, sizeof(*net->ipv6.ip6_null_entry), @@ -2669,7 +2665,7 @@ static int ip6_route_net_init(struct net *net) goto out_ip6_dst_ops; net->ipv6.ip6_null_entry->u.dst.path = (struct dst_entry *)net->ipv6.ip6_null_entry; - net->ipv6.ip6_null_entry->u.dst.ops = net->ipv6.ip6_dst_ops; + net->ipv6.ip6_null_entry->u.dst.ops = &net->ipv6.ip6_dst_ops; #ifdef CONFIG_IPV6_MULTIPLE_TABLES net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, @@ -2679,7 +2675,7 @@ static int ip6_route_net_init(struct net *net) goto out_ip6_null_entry; net->ipv6.ip6_prohibit_entry->u.dst.path = (struct dst_entry *)net->ipv6.ip6_prohibit_entry; - net->ipv6.ip6_prohibit_entry->u.dst.ops = net->ipv6.ip6_dst_ops; + net->ipv6.ip6_prohibit_entry->u.dst.ops = &net->ipv6.ip6_dst_ops; net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, sizeof(*net->ipv6.ip6_blk_hole_entry), @@ -2688,7 +2684,7 @@ static int ip6_route_net_init(struct net *net) goto out_ip6_prohibit_entry; net->ipv6.ip6_blk_hole_entry->u.dst.path = (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; - net->ipv6.ip6_blk_hole_entry->u.dst.ops = net->ipv6.ip6_dst_ops; + net->ipv6.ip6_blk_hole_entry->u.dst.ops = &net->ipv6.ip6_dst_ops; #endif net->ipv6.sysctl.flush_delay = 0; @@ -2717,8 +2713,6 @@ out_ip6_null_entry: kfree(net->ipv6.ip6_null_entry); #endif out_ip6_dst_ops: - release_net(net->ipv6.ip6_dst_ops->dst_net); - kfree(net->ipv6.ip6_dst_ops); goto out; } @@ -2733,8 +2727,6 @@ static void ip6_route_net_exit(struct net *net) kfree(net->ipv6.ip6_prohibit_entry); kfree(net->ipv6.ip6_blk_hole_entry); #endif - release_net(net->ipv6.ip6_dst_ops->dst_net); - kfree(net->ipv6.ip6_dst_ops); } static struct pernet_operations ip6_route_net_ops = { diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index d335a306a4db..0ae4f6448187 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -609,7 +609,8 @@ static inline __be32 try_6to4(struct in6_addr *v6dst) * and that skb is filled properly by that function. */ -static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, + struct net_device *dev) { struct ip_tunnel *tunnel = netdev_priv(dev); struct net_device_stats *stats = &tunnel->dev->stats; @@ -778,7 +779,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) iph->version = 4; iph->ihl = sizeof(struct iphdr)>>2; if (mtu > IPV6_MIN_MTU) - iph->frag_off = htons(IP_DF); + iph->frag_off = tiph->frag_off; else iph->frag_off = 0; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index d849dd53b788..3aae0f217d61 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -75,11 +75,11 @@ static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); -static struct inet_connection_sock_af_ops ipv6_mapped; -static struct inet_connection_sock_af_ops ipv6_specific; +static const struct inet_connection_sock_af_ops ipv6_mapped; +static const struct inet_connection_sock_af_ops ipv6_specific; #ifdef CONFIG_TCP_MD5SIG -static struct tcp_sock_af_ops tcp_sock_ipv6_specific; -static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; +static const struct tcp_sock_af_ops tcp_sock_ipv6_specific; +static const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; #else static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, struct in6_addr *addr) @@ -591,7 +591,7 @@ static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer, } sk->sk_route_caps &= ~NETIF_F_GSO_MASK; } - if (tcp_alloc_md5sig_pool() == NULL) { + if (tcp_alloc_md5sig_pool(sk) == NULL) { kfree(newkey); return -ENOMEM; } @@ -894,7 +894,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 = { +static const 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, }; @@ -1003,6 +1003,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len); t1 = (struct tcphdr *) skb_push(buff, tot_len); + skb_reset_transport_header(skb); /* Swap the send and the receive. */ memset(t1, 0, sizeof(*t1)); @@ -1760,7 +1761,7 @@ static int tcp_v6_remember_stamp(struct sock *sk) return 0; } -static struct inet_connection_sock_af_ops ipv6_specific = { +static const struct inet_connection_sock_af_ops ipv6_specific = { .queue_xmit = inet6_csk_xmit, .send_check = tcp_v6_send_check, .rebuild_header = inet6_sk_rebuild_header, @@ -1780,7 +1781,7 @@ static struct inet_connection_sock_af_ops ipv6_specific = { }; #ifdef CONFIG_TCP_MD5SIG -static struct tcp_sock_af_ops tcp_sock_ipv6_specific = { +static const struct tcp_sock_af_ops tcp_sock_ipv6_specific = { .md5_lookup = tcp_v6_md5_lookup, .calc_md5_hash = tcp_v6_md5_hash_skb, .md5_add = tcp_v6_md5_add_func, @@ -1792,7 +1793,7 @@ static struct tcp_sock_af_ops tcp_sock_ipv6_specific = { * TCP over IPv4 via INET6 API */ -static struct inet_connection_sock_af_ops ipv6_mapped = { +static const struct inet_connection_sock_af_ops ipv6_mapped = { .queue_xmit = ip_queue_xmit, .send_check = tcp_v4_send_check, .rebuild_header = inet_sk_rebuild_header, @@ -1812,7 +1813,7 @@ static struct inet_connection_sock_af_ops ipv6_mapped = { }; #ifdef CONFIG_TCP_MD5SIG -static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = { +static const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = { .md5_lookup = tcp_v4_md5_lookup, .calc_md5_hash = tcp_v4_md5_hash_skb, .md5_add = tcp_v6_md5_add_func, diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index d79fa6724451..164040613c2e 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -724,12 +724,18 @@ static int udp_v6_push_pending_frames(struct sock *sk) send: err = ip6_push_pending_frames(sk); + if (err) { + if (err == -ENOBUFS && !inet6_sk(sk)->recverr) { + UDP6_INC_STATS_USER(sock_net(sk), + UDP_MIB_SNDBUFERRORS, is_udplite); + err = 0; + } + } else + UDP6_INC_STATS_USER(sock_net(sk), + UDP_MIB_OUTDATAGRAMS, is_udplite); out: up->len = 0; up->pending = 0; - if (!err) - UDP6_INC_STATS_USER(sock_net(sk), - UDP_MIB_OUTDATAGRAMS, is_udplite); return err; } @@ -946,11 +952,8 @@ do_udp_sendmsg: hlimit = ip6_dst_hoplimit(dst); } - if (tclass < 0) { + if (tclass < 0) tclass = np->tclass; - if (tclass < 0) - tclass = 0; - } if (msg->msg_flags&MSG_CONFIRM) goto do_confirm; |