aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/devinet.c21
-rw-r--r--net/ipv4/ip_output.c1
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_tcp.c1
-rw-r--r--net/ipv4/netfilter/ip_queue.c20
-rw-r--r--net/ipv4/netfilter/iptable_raw.c6
-rw-r--r--net/ipv4/tcp_diag.c3
-rw-r--r--net/ipv4/tcp_ipv4.c7
-rw-r--r--net/ipv4/xfrm4_policy.c42
8 files changed, 75 insertions, 26 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index eea7ef010776..abbc6d5c183e 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1107,17 +1107,18 @@ static void rtmsg_ifa(int event, struct in_ifaddr* ifa)
1107 } 1107 }
1108} 1108}
1109 1109
1110static struct rtnetlink_link inet_rtnetlink_table[RTM_MAX - RTM_BASE + 1] = { 1110static struct rtnetlink_link inet_rtnetlink_table[RTM_NR_MSGTYPES] = {
1111 [4] = { .doit = inet_rtm_newaddr, }, 1111 [RTM_NEWADDR - RTM_BASE] = { .doit = inet_rtm_newaddr, },
1112 [5] = { .doit = inet_rtm_deladdr, }, 1112 [RTM_DELADDR - RTM_BASE] = { .doit = inet_rtm_deladdr, },
1113 [6] = { .dumpit = inet_dump_ifaddr, }, 1113 [RTM_GETADDR - RTM_BASE] = { .dumpit = inet_dump_ifaddr, },
1114 [8] = { .doit = inet_rtm_newroute, }, 1114 [RTM_NEWROUTE - RTM_BASE] = { .doit = inet_rtm_newroute, },
1115 [9] = { .doit = inet_rtm_delroute, }, 1115 [RTM_DELROUTE - RTM_BASE] = { .doit = inet_rtm_delroute, },
1116 [10] = { .doit = inet_rtm_getroute, .dumpit = inet_dump_fib, }, 1116 [RTM_GETROUTE - RTM_BASE] = { .doit = inet_rtm_getroute,
1117 .dumpit = inet_dump_fib, },
1117#ifdef CONFIG_IP_MULTIPLE_TABLES 1118#ifdef CONFIG_IP_MULTIPLE_TABLES
1118 [16] = { .doit = inet_rtm_newrule, }, 1119 [RTM_NEWRULE - RTM_BASE] = { .doit = inet_rtm_newrule, },
1119 [17] = { .doit = inet_rtm_delrule, }, 1120 [RTM_DELRULE - RTM_BASE] = { .doit = inet_rtm_delrule, },
1120 [18] = { .dumpit = inet_dump_rules, }, 1121 [RTM_GETRULE - RTM_BASE] = { .dumpit = inet_dump_rules, },
1121#endif 1122#endif
1122}; 1123};
1123 1124
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 38f69532a029..24fe3e00b42b 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -111,6 +111,7 @@ static int ip_dev_loopback_xmit(struct sk_buff *newskb)
111#ifdef CONFIG_NETFILTER_DEBUG 111#ifdef CONFIG_NETFILTER_DEBUG
112 nf_debug_ip_loopback_xmit(newskb); 112 nf_debug_ip_loopback_xmit(newskb);
113#endif 113#endif
114 nf_reset(newskb);
114 netif_rx(newskb); 115 netif_rx(newskb);
115 return 0; 116 return 0;
116} 117}
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
index 2b87c1974be6..721ddbf522b4 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
@@ -819,6 +819,7 @@ static int tcp_error(struct sk_buff *skb,
819 */ 819 */
820 /* FIXME: Source route IP option packets --RR */ 820 /* FIXME: Source route IP option packets --RR */
821 if (hooknum == NF_IP_PRE_ROUTING 821 if (hooknum == NF_IP_PRE_ROUTING
822 && skb->ip_summed != CHECKSUM_UNNECESSARY
822 && csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP, 823 && csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP,
823 skb->ip_summed == CHECKSUM_HW ? skb->csum 824 skb->ip_summed == CHECKSUM_HW ? skb->csum
824 : skb_checksum(skb, iph->ihl*4, tcplen, 0))) { 825 : skb_checksum(skb, iph->ihl*4, tcplen, 0))) {
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 9e40dffc204f..e5746b674413 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -546,20 +546,18 @@ ipq_rcv_skb(struct sk_buff *skb)
546static void 546static void
547ipq_rcv_sk(struct sock *sk, int len) 547ipq_rcv_sk(struct sock *sk, int len)
548{ 548{
549 do { 549 struct sk_buff *skb;
550 struct sk_buff *skb; 550 unsigned int qlen;
551 551
552 if (down_trylock(&ipqnl_sem)) 552 down(&ipqnl_sem);
553 return;
554 553
555 while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { 554 for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) {
556 ipq_rcv_skb(skb); 555 skb = skb_dequeue(&sk->sk_receive_queue);
557 kfree_skb(skb); 556 ipq_rcv_skb(skb);
558 } 557 kfree_skb(skb);
558 }
559 559
560 up(&ipqnl_sem); 560 up(&ipqnl_sem);
561
562 } while (ipqnl && ipqnl->sk_receive_queue.qlen);
563} 561}
564 562
565static int 563static int
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index 01b4a3c814d3..47449ba83eb9 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -103,13 +103,15 @@ static struct nf_hook_ops ipt_ops[] = {
103 .hook = ipt_hook, 103 .hook = ipt_hook,
104 .pf = PF_INET, 104 .pf = PF_INET,
105 .hooknum = NF_IP_PRE_ROUTING, 105 .hooknum = NF_IP_PRE_ROUTING,
106 .priority = NF_IP_PRI_RAW 106 .priority = NF_IP_PRI_RAW,
107 .owner = THIS_MODULE,
107 }, 108 },
108 { 109 {
109 .hook = ipt_hook, 110 .hook = ipt_hook,
110 .pf = PF_INET, 111 .pf = PF_INET,
111 .hooknum = NF_IP_LOCAL_OUT, 112 .hooknum = NF_IP_LOCAL_OUT,
112 .priority = NF_IP_PRI_RAW 113 .priority = NF_IP_PRI_RAW,
114 .owner = THIS_MODULE,
113 }, 115 },
114}; 116};
115 117
diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c
index 313c1408da33..8faa8948f75c 100644
--- a/net/ipv4/tcp_diag.c
+++ b/net/ipv4/tcp_diag.c
@@ -777,8 +777,9 @@ static inline void tcpdiag_rcv_skb(struct sk_buff *skb)
777static void tcpdiag_rcv(struct sock *sk, int len) 777static void tcpdiag_rcv(struct sock *sk, int len)
778{ 778{
779 struct sk_buff *skb; 779 struct sk_buff *skb;
780 unsigned int qlen = skb_queue_len(&sk->sk_receive_queue);
780 781
781 while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { 782 while (qlen-- && (skb = skb_dequeue(&sk->sk_receive_queue))) {
782 tcpdiag_rcv_skb(skb); 783 tcpdiag_rcv_skb(skb);
783 kfree_skb(skb); 784 kfree_skb(skb);
784 } 785 }
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 3ac6659869c4..dad98e4a5043 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -222,10 +222,13 @@ static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
222 int rover; 222 int rover;
223 223
224 spin_lock(&tcp_portalloc_lock); 224 spin_lock(&tcp_portalloc_lock);
225 rover = tcp_port_rover; 225 if (tcp_port_rover < low)
226 rover = low;
227 else
228 rover = tcp_port_rover;
226 do { 229 do {
227 rover++; 230 rover++;
228 if (rover < low || rover > high) 231 if (rover > high)
229 rover = low; 232 rover = low;
230 head = &tcp_bhash[tcp_bhashfn(rover)]; 233 head = &tcp_bhash[tcp_bhashfn(rover)];
231 spin_lock(&head->lock); 234 spin_lock(&head->lock);
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 7fe2afd2e669..b2b60f3e9cdd 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -8,7 +8,10 @@
8 * 8 *
9 */ 9 */
10 10
11#include <asm/bug.h>
12#include <linux/compiler.h>
11#include <linux/config.h> 13#include <linux/config.h>
14#include <linux/inetdevice.h>
12#include <net/xfrm.h> 15#include <net/xfrm.h>
13#include <net/ip.h> 16#include <net/ip.h>
14 17
@@ -152,6 +155,8 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
152 x->u.rt.rt_dst = rt0->rt_dst; 155 x->u.rt.rt_dst = rt0->rt_dst;
153 x->u.rt.rt_gateway = rt->rt_gateway; 156 x->u.rt.rt_gateway = rt->rt_gateway;
154 x->u.rt.rt_spec_dst = rt0->rt_spec_dst; 157 x->u.rt.rt_spec_dst = rt0->rt_spec_dst;
158 x->u.rt.idev = rt0->idev;
159 in_dev_hold(rt0->idev);
155 header_len -= x->u.dst.xfrm->props.header_len; 160 header_len -= x->u.dst.xfrm->props.header_len;
156 trailer_len -= x->u.dst.xfrm->props.trailer_len; 161 trailer_len -= x->u.dst.xfrm->props.trailer_len;
157 } 162 }
@@ -243,11 +248,48 @@ static void xfrm4_update_pmtu(struct dst_entry *dst, u32 mtu)
243 path->ops->update_pmtu(path, mtu); 248 path->ops->update_pmtu(path, mtu);
244} 249}
245 250
251static void xfrm4_dst_destroy(struct dst_entry *dst)
252{
253 struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
254
255 if (likely(xdst->u.rt.idev))
256 in_dev_put(xdst->u.rt.idev);
257 xfrm_dst_destroy(xdst);
258}
259
260static void xfrm4_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
261 int unregister)
262{
263 struct xfrm_dst *xdst;
264
265 if (!unregister)
266 return;
267
268 xdst = (struct xfrm_dst *)dst;
269 if (xdst->u.rt.idev->dev == dev) {
270 struct in_device *loopback_idev = in_dev_get(&loopback_dev);
271 BUG_ON(!loopback_idev);
272
273 do {
274 in_dev_put(xdst->u.rt.idev);
275 xdst->u.rt.idev = loopback_idev;
276 in_dev_hold(loopback_idev);
277 xdst = (struct xfrm_dst *)xdst->u.dst.child;
278 } while (xdst->u.dst.xfrm);
279
280 __in_dev_put(loopback_idev);
281 }
282
283 xfrm_dst_ifdown(dst, dev);
284}
285
246static struct dst_ops xfrm4_dst_ops = { 286static struct dst_ops xfrm4_dst_ops = {
247 .family = AF_INET, 287 .family = AF_INET,
248 .protocol = __constant_htons(ETH_P_IP), 288 .protocol = __constant_htons(ETH_P_IP),
249 .gc = xfrm4_garbage_collect, 289 .gc = xfrm4_garbage_collect,
250 .update_pmtu = xfrm4_update_pmtu, 290 .update_pmtu = xfrm4_update_pmtu,
291 .destroy = xfrm4_dst_destroy,
292 .ifdown = xfrm4_dst_ifdown,
251 .gc_thresh = 1024, 293 .gc_thresh = 1024,
252 .entry_size = sizeof(struct xfrm_dst), 294 .entry_size = sizeof(struct xfrm_dst),
253}; 295};