diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/ipv4/tcp_output.c | 12 | ||||
| -rw-r--r-- | net/ipv4/udp.c | 7 | ||||
| -rw-r--r-- | net/ipv6/ip6_output.c | 67 | ||||
| -rw-r--r-- | net/ipv6/ip6mr.c | 1 | ||||
| -rw-r--r-- | net/packet/af_packet.c | 17 | ||||
| -rw-r--r-- | net/sunrpc/Kconfig | 2 |
6 files changed, 74 insertions, 32 deletions
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 557fe16cbfb0..dda42f0bd7a3 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
| @@ -663,14 +663,10 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
| 663 | th->urg_ptr = 0; | 663 | th->urg_ptr = 0; |
| 664 | 664 | ||
| 665 | /* The urg_mode check is necessary during a below snd_una win probe */ | 665 | /* The urg_mode check is necessary during a below snd_una win probe */ |
| 666 | if (unlikely(tcp_urg_mode(tp))) { | 666 | if (unlikely(tcp_urg_mode(tp) && |
| 667 | if (between(tp->snd_up, tcb->seq + 1, tcb->seq + 0xFFFF)) { | 667 | between(tp->snd_up, tcb->seq + 1, tcb->seq + 0xFFFF))) { |
| 668 | th->urg_ptr = htons(tp->snd_up - tcb->seq); | 668 | th->urg_ptr = htons(tp->snd_up - tcb->seq); |
| 669 | th->urg = 1; | 669 | th->urg = 1; |
| 670 | } else if (after(tcb->seq + 0xFFFF, tp->snd_nxt)) { | ||
| 671 | th->urg_ptr = 0xFFFF; | ||
| 672 | th->urg = 1; | ||
| 673 | } | ||
| 674 | } | 670 | } |
| 675 | 671 | ||
| 676 | tcp_options_write((__be32 *)(th + 1), tp, &opts, &md5_hash_location); | 672 | tcp_options_write((__be32 *)(th + 1), tp, &opts, &md5_hash_location); |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index b7faffe5c029..cc3a0a06c004 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
| @@ -1015,9 +1015,11 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
| 1015 | 1015 | ||
| 1016 | if ((rc = sock_queue_rcv_skb(sk, skb)) < 0) { | 1016 | if ((rc = sock_queue_rcv_skb(sk, skb)) < 0) { |
| 1017 | /* Note that an ENOMEM error is charged twice */ | 1017 | /* Note that an ENOMEM error is charged twice */ |
| 1018 | if (rc == -ENOMEM) | 1018 | if (rc == -ENOMEM) { |
| 1019 | UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS, | 1019 | UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS, |
| 1020 | is_udplite); | 1020 | is_udplite); |
| 1021 | atomic_inc(&sk->sk_drops); | ||
| 1022 | } | ||
| 1021 | goto drop; | 1023 | goto drop; |
| 1022 | } | 1024 | } |
| 1023 | 1025 | ||
| @@ -1229,7 +1231,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
| 1229 | int proto) | 1231 | int proto) |
| 1230 | { | 1232 | { |
| 1231 | struct sock *sk; | 1233 | struct sock *sk; |
| 1232 | struct udphdr *uh = udp_hdr(skb); | 1234 | struct udphdr *uh; |
| 1233 | unsigned short ulen; | 1235 | unsigned short ulen; |
| 1234 | struct rtable *rt = (struct rtable*)skb->dst; | 1236 | struct rtable *rt = (struct rtable*)skb->dst; |
| 1235 | __be32 saddr = ip_hdr(skb)->saddr; | 1237 | __be32 saddr = ip_hdr(skb)->saddr; |
| @@ -1242,6 +1244,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
| 1242 | if (!pskb_may_pull(skb, sizeof(struct udphdr))) | 1244 | if (!pskb_may_pull(skb, sizeof(struct udphdr))) |
| 1243 | goto drop; /* No space for header. */ | 1245 | goto drop; /* No space for header. */ |
| 1244 | 1246 | ||
| 1247 | uh = udp_hdr(skb); | ||
| 1245 | ulen = ntohs(uh->len); | 1248 | ulen = ntohs(uh->len); |
| 1246 | if (ulen > skb->len) | 1249 | if (ulen > skb->len) |
| 1247 | goto short_packet; | 1250 | goto short_packet; |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 4b15938bef4d..9fb49c3b518a 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
| @@ -1105,6 +1105,18 @@ static inline int ip6_ufo_append_data(struct sock *sk, | |||
| 1105 | return err; | 1105 | return err; |
| 1106 | } | 1106 | } |
| 1107 | 1107 | ||
| 1108 | static inline struct ipv6_opt_hdr *ip6_opt_dup(struct ipv6_opt_hdr *src, | ||
| 1109 | gfp_t gfp) | ||
| 1110 | { | ||
| 1111 | return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL; | ||
| 1112 | } | ||
| 1113 | |||
| 1114 | static inline struct ipv6_rt_hdr *ip6_rthdr_dup(struct ipv6_rt_hdr *src, | ||
| 1115 | gfp_t gfp) | ||
| 1116 | { | ||
| 1117 | return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL; | ||
| 1118 | } | ||
| 1119 | |||
| 1108 | int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | 1120 | int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, |
| 1109 | int offset, int len, int odd, struct sk_buff *skb), | 1121 | int offset, int len, int odd, struct sk_buff *skb), |
| 1110 | void *from, int length, int transhdrlen, | 1122 | void *from, int length, int transhdrlen, |
| @@ -1130,17 +1142,37 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
| 1130 | * setup for corking | 1142 | * setup for corking |
| 1131 | */ | 1143 | */ |
| 1132 | if (opt) { | 1144 | if (opt) { |
| 1133 | if (np->cork.opt == NULL) { | 1145 | if (WARN_ON(np->cork.opt)) |
| 1134 | np->cork.opt = kmalloc(opt->tot_len, | ||
| 1135 | sk->sk_allocation); | ||
| 1136 | if (unlikely(np->cork.opt == NULL)) | ||
| 1137 | return -ENOBUFS; | ||
| 1138 | } else if (np->cork.opt->tot_len < opt->tot_len) { | ||
| 1139 | printk(KERN_DEBUG "ip6_append_data: invalid option length\n"); | ||
| 1140 | return -EINVAL; | 1146 | return -EINVAL; |
| 1141 | } | 1147 | |
| 1142 | memcpy(np->cork.opt, opt, opt->tot_len); | 1148 | np->cork.opt = kmalloc(opt->tot_len, sk->sk_allocation); |
| 1143 | inet->cork.flags |= IPCORK_OPT; | 1149 | if (unlikely(np->cork.opt == NULL)) |
| 1150 | return -ENOBUFS; | ||
| 1151 | |||
| 1152 | np->cork.opt->tot_len = opt->tot_len; | ||
| 1153 | np->cork.opt->opt_flen = opt->opt_flen; | ||
| 1154 | np->cork.opt->opt_nflen = opt->opt_nflen; | ||
| 1155 | |||
| 1156 | np->cork.opt->dst0opt = ip6_opt_dup(opt->dst0opt, | ||
| 1157 | sk->sk_allocation); | ||
| 1158 | if (opt->dst0opt && !np->cork.opt->dst0opt) | ||
| 1159 | return -ENOBUFS; | ||
| 1160 | |||
| 1161 | np->cork.opt->dst1opt = ip6_opt_dup(opt->dst1opt, | ||
| 1162 | sk->sk_allocation); | ||
| 1163 | if (opt->dst1opt && !np->cork.opt->dst1opt) | ||
| 1164 | return -ENOBUFS; | ||
| 1165 | |||
| 1166 | np->cork.opt->hopopt = ip6_opt_dup(opt->hopopt, | ||
| 1167 | sk->sk_allocation); | ||
| 1168 | if (opt->hopopt && !np->cork.opt->hopopt) | ||
| 1169 | return -ENOBUFS; | ||
| 1170 | |||
| 1171 | np->cork.opt->srcrt = ip6_rthdr_dup(opt->srcrt, | ||
| 1172 | sk->sk_allocation); | ||
| 1173 | if (opt->srcrt && !np->cork.opt->srcrt) | ||
| 1174 | return -ENOBUFS; | ||
| 1175 | |||
| 1144 | /* need source address above miyazawa*/ | 1176 | /* need source address above miyazawa*/ |
| 1145 | } | 1177 | } |
| 1146 | dst_hold(&rt->u.dst); | 1178 | dst_hold(&rt->u.dst); |
| @@ -1167,8 +1199,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
| 1167 | } else { | 1199 | } else { |
| 1168 | rt = (struct rt6_info *)inet->cork.dst; | 1200 | rt = (struct rt6_info *)inet->cork.dst; |
| 1169 | fl = &inet->cork.fl; | 1201 | fl = &inet->cork.fl; |
| 1170 | if (inet->cork.flags & IPCORK_OPT) | 1202 | opt = np->cork.opt; |
| 1171 | opt = np->cork.opt; | ||
| 1172 | transhdrlen = 0; | 1203 | transhdrlen = 0; |
| 1173 | exthdrlen = 0; | 1204 | exthdrlen = 0; |
| 1174 | mtu = inet->cork.fragsize; | 1205 | mtu = inet->cork.fragsize; |
| @@ -1407,9 +1438,15 @@ error: | |||
| 1407 | 1438 | ||
| 1408 | static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np) | 1439 | static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np) |
| 1409 | { | 1440 | { |
| 1410 | inet->cork.flags &= ~IPCORK_OPT; | 1441 | if (np->cork.opt) { |
| 1411 | kfree(np->cork.opt); | 1442 | kfree(np->cork.opt->dst0opt); |
| 1412 | np->cork.opt = NULL; | 1443 | kfree(np->cork.opt->dst1opt); |
| 1444 | kfree(np->cork.opt->hopopt); | ||
| 1445 | kfree(np->cork.opt->srcrt); | ||
| 1446 | kfree(np->cork.opt); | ||
| 1447 | np->cork.opt = NULL; | ||
| 1448 | } | ||
| 1449 | |||
| 1413 | if (inet->cork.dst) { | 1450 | if (inet->cork.dst) { |
| 1414 | dst_release(inet->cork.dst); | 1451 | dst_release(inet->cork.dst); |
| 1415 | inet->cork.dst = NULL; | 1452 | inet->cork.dst = NULL; |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index d19a84b79503..228be551e9c1 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
| @@ -48,6 +48,7 @@ | |||
| 48 | #include <linux/pim.h> | 48 | #include <linux/pim.h> |
| 49 | #include <net/addrconf.h> | 49 | #include <net/addrconf.h> |
| 50 | #include <linux/netfilter_ipv6.h> | 50 | #include <linux/netfilter_ipv6.h> |
| 51 | #include <net/ip6_checksum.h> | ||
| 51 | 52 | ||
| 52 | /* Big lock, protecting vif table, mrt cache and mroute socket state. | 53 | /* Big lock, protecting vif table, mrt cache and mroute socket state. |
| 53 | Note that the changes are semaphored via rtnl_lock. | 54 | Note that the changes are semaphored via rtnl_lock. |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 5f94db2f3e9e..1fc4a7885c41 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
| @@ -77,6 +77,7 @@ | |||
| 77 | #include <linux/poll.h> | 77 | #include <linux/poll.h> |
| 78 | #include <linux/module.h> | 78 | #include <linux/module.h> |
| 79 | #include <linux/init.h> | 79 | #include <linux/init.h> |
| 80 | #include <linux/mutex.h> | ||
| 80 | 81 | ||
| 81 | #ifdef CONFIG_INET | 82 | #ifdef CONFIG_INET |
| 82 | #include <net/inet_common.h> | 83 | #include <net/inet_common.h> |
| @@ -175,6 +176,7 @@ struct packet_sock { | |||
| 175 | #endif | 176 | #endif |
| 176 | struct packet_type prot_hook; | 177 | struct packet_type prot_hook; |
| 177 | spinlock_t bind_lock; | 178 | spinlock_t bind_lock; |
| 179 | struct mutex pg_vec_lock; | ||
| 178 | unsigned int running:1, /* prot_hook is attached*/ | 180 | unsigned int running:1, /* prot_hook is attached*/ |
| 179 | auxdata:1, | 181 | auxdata:1, |
| 180 | origdev:1; | 182 | origdev:1; |
| @@ -220,13 +222,13 @@ static void *packet_lookup_frame(struct packet_sock *po, unsigned int position, | |||
| 220 | h.raw = po->pg_vec[pg_vec_pos] + (frame_offset * po->frame_size); | 222 | h.raw = po->pg_vec[pg_vec_pos] + (frame_offset * po->frame_size); |
| 221 | switch (po->tp_version) { | 223 | switch (po->tp_version) { |
| 222 | case TPACKET_V1: | 224 | case TPACKET_V1: |
| 223 | if (status != h.h1->tp_status ? TP_STATUS_USER : | 225 | if (status != (h.h1->tp_status ? TP_STATUS_USER : |
| 224 | TP_STATUS_KERNEL) | 226 | TP_STATUS_KERNEL)) |
| 225 | return NULL; | 227 | return NULL; |
| 226 | break; | 228 | break; |
| 227 | case TPACKET_V2: | 229 | case TPACKET_V2: |
| 228 | if (status != h.h2->tp_status ? TP_STATUS_USER : | 230 | if (status != (h.h2->tp_status ? TP_STATUS_USER : |
| 229 | TP_STATUS_KERNEL) | 231 | TP_STATUS_KERNEL)) |
| 230 | return NULL; | 232 | return NULL; |
| 231 | break; | 233 | break; |
| 232 | } | 234 | } |
| @@ -1069,6 +1071,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol) | |||
| 1069 | */ | 1071 | */ |
| 1070 | 1072 | ||
| 1071 | spin_lock_init(&po->bind_lock); | 1073 | spin_lock_init(&po->bind_lock); |
| 1074 | mutex_init(&po->pg_vec_lock); | ||
| 1072 | po->prot_hook.func = packet_rcv; | 1075 | po->prot_hook.func = packet_rcv; |
| 1073 | 1076 | ||
| 1074 | if (sock->type == SOCK_PACKET) | 1077 | if (sock->type == SOCK_PACKET) |
| @@ -1865,6 +1868,7 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing | |||
| 1865 | synchronize_net(); | 1868 | synchronize_net(); |
| 1866 | 1869 | ||
| 1867 | err = -EBUSY; | 1870 | err = -EBUSY; |
| 1871 | mutex_lock(&po->pg_vec_lock); | ||
| 1868 | if (closing || atomic_read(&po->mapped) == 0) { | 1872 | if (closing || atomic_read(&po->mapped) == 0) { |
| 1869 | err = 0; | 1873 | err = 0; |
| 1870 | #define XC(a, b) ({ __typeof__ ((a)) __t; __t = (a); (a) = (b); __t; }) | 1874 | #define XC(a, b) ({ __typeof__ ((a)) __t; __t = (a); (a) = (b); __t; }) |
| @@ -1886,6 +1890,7 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing | |||
| 1886 | if (atomic_read(&po->mapped)) | 1890 | if (atomic_read(&po->mapped)) |
| 1887 | printk(KERN_DEBUG "packet_mmap: vma is busy: %d\n", atomic_read(&po->mapped)); | 1891 | printk(KERN_DEBUG "packet_mmap: vma is busy: %d\n", atomic_read(&po->mapped)); |
| 1888 | } | 1892 | } |
| 1893 | mutex_unlock(&po->pg_vec_lock); | ||
| 1889 | 1894 | ||
| 1890 | spin_lock(&po->bind_lock); | 1895 | spin_lock(&po->bind_lock); |
| 1891 | if (was_running && !po->running) { | 1896 | if (was_running && !po->running) { |
| @@ -1918,7 +1923,7 @@ static int packet_mmap(struct file *file, struct socket *sock, struct vm_area_st | |||
| 1918 | 1923 | ||
| 1919 | size = vma->vm_end - vma->vm_start; | 1924 | size = vma->vm_end - vma->vm_start; |
| 1920 | 1925 | ||
| 1921 | lock_sock(sk); | 1926 | mutex_lock(&po->pg_vec_lock); |
| 1922 | if (po->pg_vec == NULL) | 1927 | if (po->pg_vec == NULL) |
| 1923 | goto out; | 1928 | goto out; |
| 1924 | if (size != po->pg_vec_len*po->pg_vec_pages*PAGE_SIZE) | 1929 | if (size != po->pg_vec_len*po->pg_vec_pages*PAGE_SIZE) |
| @@ -1941,7 +1946,7 @@ static int packet_mmap(struct file *file, struct socket *sock, struct vm_area_st | |||
| 1941 | err = 0; | 1946 | err = 0; |
| 1942 | 1947 | ||
| 1943 | out: | 1948 | out: |
| 1944 | release_sock(sk); | 1949 | mutex_unlock(&po->pg_vec_lock); |
| 1945 | return err; | 1950 | return err; |
| 1946 | } | 1951 | } |
| 1947 | #endif | 1952 | #endif |
diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig index dcef600d0bf5..5592883e1e4a 100644 --- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig | |||
| @@ -6,7 +6,7 @@ config SUNRPC_GSS | |||
| 6 | 6 | ||
| 7 | config SUNRPC_XPRT_RDMA | 7 | config SUNRPC_XPRT_RDMA |
| 8 | tristate | 8 | tristate |
| 9 | depends on SUNRPC && INFINIBAND && EXPERIMENTAL | 9 | depends on SUNRPC && INFINIBAND && INFINIBAND_ADDR_TRANS && EXPERIMENTAL |
| 10 | default SUNRPC && INFINIBAND | 10 | default SUNRPC && INFINIBAND |
| 11 | help | 11 | help |
| 12 | This option allows the NFS client and server to support | 12 | This option allows the NFS client and server to support |
