diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/fib_frontend.c | 5 | ||||
-rw-r--r-- | net/ipv4/ip_gre.c | 28 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_core.c | 3 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_helper.c | 34 | ||||
-rw-r--r-- | net/ipv4/route.c | 8 | ||||
-rw-r--r-- | net/ipv4/udp.c | 4 |
6 files changed, 51 insertions, 31 deletions
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index f73dbed0f0d7..816e2180bd60 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -229,14 +229,17 @@ unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev, | |||
229 | */ | 229 | */ |
230 | 230 | ||
231 | int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | 231 | int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, |
232 | struct net_device *dev, __be32 *spec_dst, u32 *itag) | 232 | struct net_device *dev, __be32 *spec_dst, |
233 | u32 *itag, u32 mark) | ||
233 | { | 234 | { |
234 | struct in_device *in_dev; | 235 | struct in_device *in_dev; |
235 | struct flowi fl = { .nl_u = { .ip4_u = | 236 | struct flowi fl = { .nl_u = { .ip4_u = |
236 | { .daddr = src, | 237 | { .daddr = src, |
237 | .saddr = dst, | 238 | .saddr = dst, |
238 | .tos = tos } }, | 239 | .tos = tos } }, |
240 | .mark = mark, | ||
239 | .iif = oif }; | 241 | .iif = oif }; |
242 | |||
240 | struct fib_result res; | 243 | struct fib_result res; |
241 | int no_addr, rpf; | 244 | int no_addr, rpf; |
242 | int ret; | 245 | int ret; |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index a77807d449e3..71a3242fb7d0 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -1476,7 +1476,7 @@ static void ipgre_tap_setup(struct net_device *dev) | |||
1476 | 1476 | ||
1477 | ether_setup(dev); | 1477 | ether_setup(dev); |
1478 | 1478 | ||
1479 | dev->netdev_ops = &ipgre_netdev_ops; | 1479 | dev->netdev_ops = &ipgre_tap_netdev_ops; |
1480 | dev->destructor = free_netdev; | 1480 | dev->destructor = free_netdev; |
1481 | 1481 | ||
1482 | dev->iflink = 0; | 1482 | dev->iflink = 0; |
@@ -1537,25 +1537,29 @@ static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[], | |||
1537 | if (t->dev != dev) | 1537 | if (t->dev != dev) |
1538 | return -EEXIST; | 1538 | return -EEXIST; |
1539 | } else { | 1539 | } else { |
1540 | unsigned nflags = 0; | ||
1541 | |||
1542 | t = nt; | 1540 | t = nt; |
1543 | 1541 | ||
1544 | if (ipv4_is_multicast(p.iph.daddr)) | 1542 | if (dev->type != ARPHRD_ETHER) { |
1545 | nflags = IFF_BROADCAST; | 1543 | unsigned nflags = 0; |
1546 | else if (p.iph.daddr) | ||
1547 | nflags = IFF_POINTOPOINT; | ||
1548 | 1544 | ||
1549 | if ((dev->flags ^ nflags) & | 1545 | if (ipv4_is_multicast(p.iph.daddr)) |
1550 | (IFF_POINTOPOINT | IFF_BROADCAST)) | 1546 | nflags = IFF_BROADCAST; |
1551 | return -EINVAL; | 1547 | else if (p.iph.daddr) |
1548 | nflags = IFF_POINTOPOINT; | ||
1549 | |||
1550 | if ((dev->flags ^ nflags) & | ||
1551 | (IFF_POINTOPOINT | IFF_BROADCAST)) | ||
1552 | return -EINVAL; | ||
1553 | } | ||
1552 | 1554 | ||
1553 | ipgre_tunnel_unlink(ign, t); | 1555 | ipgre_tunnel_unlink(ign, t); |
1554 | t->parms.iph.saddr = p.iph.saddr; | 1556 | t->parms.iph.saddr = p.iph.saddr; |
1555 | t->parms.iph.daddr = p.iph.daddr; | 1557 | t->parms.iph.daddr = p.iph.daddr; |
1556 | t->parms.i_key = p.i_key; | 1558 | t->parms.i_key = p.i_key; |
1557 | memcpy(dev->dev_addr, &p.iph.saddr, 4); | 1559 | if (dev->type != ARPHRD_ETHER) { |
1558 | memcpy(dev->broadcast, &p.iph.daddr, 4); | 1560 | memcpy(dev->dev_addr, &p.iph.saddr, 4); |
1561 | memcpy(dev->broadcast, &p.iph.daddr, 4); | ||
1562 | } | ||
1559 | ipgre_tunnel_link(ign, t); | 1563 | ipgre_tunnel_link(ign, t); |
1560 | netdev_state_change(dev); | 1564 | netdev_state_change(dev); |
1561 | } | 1565 | } |
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 68afc6ecd343..fe1a64479dd0 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c | |||
@@ -750,6 +750,8 @@ static int __init nf_nat_init(void) | |||
750 | BUG_ON(nfnetlink_parse_nat_setup_hook != NULL); | 750 | BUG_ON(nfnetlink_parse_nat_setup_hook != NULL); |
751 | rcu_assign_pointer(nfnetlink_parse_nat_setup_hook, | 751 | rcu_assign_pointer(nfnetlink_parse_nat_setup_hook, |
752 | nfnetlink_parse_nat_setup); | 752 | nfnetlink_parse_nat_setup); |
753 | BUG_ON(nf_ct_nat_offset != NULL); | ||
754 | rcu_assign_pointer(nf_ct_nat_offset, nf_nat_get_offset); | ||
753 | return 0; | 755 | return 0; |
754 | 756 | ||
755 | cleanup_extend: | 757 | cleanup_extend: |
@@ -764,6 +766,7 @@ static void __exit nf_nat_cleanup(void) | |||
764 | nf_ct_extend_unregister(&nat_extend); | 766 | nf_ct_extend_unregister(&nat_extend); |
765 | rcu_assign_pointer(nf_nat_seq_adjust_hook, NULL); | 767 | rcu_assign_pointer(nf_nat_seq_adjust_hook, NULL); |
766 | rcu_assign_pointer(nfnetlink_parse_nat_setup_hook, NULL); | 768 | rcu_assign_pointer(nfnetlink_parse_nat_setup_hook, NULL); |
769 | rcu_assign_pointer(nf_ct_nat_offset, NULL); | ||
767 | synchronize_net(); | 770 | synchronize_net(); |
768 | } | 771 | } |
769 | 772 | ||
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index 09172a65d9b6..f9520fa3aba9 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c | |||
@@ -73,6 +73,28 @@ adjust_tcp_sequence(u32 seq, | |||
73 | DUMP_OFFSET(this_way); | 73 | DUMP_OFFSET(this_way); |
74 | } | 74 | } |
75 | 75 | ||
76 | /* Get the offset value, for conntrack */ | ||
77 | s16 nf_nat_get_offset(const struct nf_conn *ct, | ||
78 | enum ip_conntrack_dir dir, | ||
79 | u32 seq) | ||
80 | { | ||
81 | struct nf_conn_nat *nat = nfct_nat(ct); | ||
82 | struct nf_nat_seq *this_way; | ||
83 | s16 offset; | ||
84 | |||
85 | if (!nat) | ||
86 | return 0; | ||
87 | |||
88 | this_way = &nat->seq[dir]; | ||
89 | spin_lock_bh(&nf_nat_seqofs_lock); | ||
90 | offset = after(seq, this_way->correction_pos) | ||
91 | ? this_way->offset_after : this_way->offset_before; | ||
92 | spin_unlock_bh(&nf_nat_seqofs_lock); | ||
93 | |||
94 | return offset; | ||
95 | } | ||
96 | EXPORT_SYMBOL_GPL(nf_nat_get_offset); | ||
97 | |||
76 | /* Frobs data inside this packet, which is linear. */ | 98 | /* Frobs data inside this packet, which is linear. */ |
77 | static void mangle_contents(struct sk_buff *skb, | 99 | static void mangle_contents(struct sk_buff *skb, |
78 | unsigned int dataoff, | 100 | unsigned int dataoff, |
@@ -189,11 +211,6 @@ nf_nat_mangle_tcp_packet(struct sk_buff *skb, | |||
189 | adjust_tcp_sequence(ntohl(tcph->seq), | 211 | adjust_tcp_sequence(ntohl(tcph->seq), |
190 | (int)rep_len - (int)match_len, | 212 | (int)rep_len - (int)match_len, |
191 | ct, ctinfo); | 213 | ct, ctinfo); |
192 | /* Tell TCP window tracking about seq change */ | ||
193 | nf_conntrack_tcp_update(skb, ip_hdrlen(skb), | ||
194 | ct, CTINFO2DIR(ctinfo), | ||
195 | (int)rep_len - (int)match_len); | ||
196 | |||
197 | nf_conntrack_event_cache(IPCT_NATSEQADJ, ct); | 214 | nf_conntrack_event_cache(IPCT_NATSEQADJ, ct); |
198 | } | 215 | } |
199 | return 1; | 216 | return 1; |
@@ -415,12 +432,7 @@ nf_nat_seq_adjust(struct sk_buff *skb, | |||
415 | tcph->seq = newseq; | 432 | tcph->seq = newseq; |
416 | tcph->ack_seq = newack; | 433 | tcph->ack_seq = newack; |
417 | 434 | ||
418 | if (!nf_nat_sack_adjust(skb, tcph, ct, ctinfo)) | 435 | return nf_nat_sack_adjust(skb, tcph, ct, ctinfo); |
419 | return 0; | ||
420 | |||
421 | nf_conntrack_tcp_update(skb, ip_hdrlen(skb), ct, dir, seqoff); | ||
422 | |||
423 | return 1; | ||
424 | } | 436 | } |
425 | 437 | ||
426 | /* Setup NAT on this expected conntrack so it follows master. */ | 438 | /* Setup NAT on this expected conntrack so it follows master. */ |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 68fb22702051..ff258b57680b 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -1851,7 +1851,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
1851 | goto e_inval; | 1851 | goto e_inval; |
1852 | spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); | 1852 | spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); |
1853 | } else if (fib_validate_source(saddr, 0, tos, 0, | 1853 | } else if (fib_validate_source(saddr, 0, tos, 0, |
1854 | dev, &spec_dst, &itag) < 0) | 1854 | dev, &spec_dst, &itag, 0) < 0) |
1855 | goto e_inval; | 1855 | goto e_inval; |
1856 | 1856 | ||
1857 | rth = dst_alloc(&ipv4_dst_ops); | 1857 | rth = dst_alloc(&ipv4_dst_ops); |
@@ -1964,7 +1964,7 @@ static int __mkroute_input(struct sk_buff *skb, | |||
1964 | 1964 | ||
1965 | 1965 | ||
1966 | err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(*res), | 1966 | err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(*res), |
1967 | in_dev->dev, &spec_dst, &itag); | 1967 | in_dev->dev, &spec_dst, &itag, skb->mark); |
1968 | if (err < 0) { | 1968 | if (err < 0) { |
1969 | ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr, | 1969 | ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr, |
1970 | saddr); | 1970 | saddr); |
@@ -2138,7 +2138,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
2138 | int result; | 2138 | int result; |
2139 | result = fib_validate_source(saddr, daddr, tos, | 2139 | result = fib_validate_source(saddr, daddr, tos, |
2140 | net->loopback_dev->ifindex, | 2140 | net->loopback_dev->ifindex, |
2141 | dev, &spec_dst, &itag); | 2141 | dev, &spec_dst, &itag, skb->mark); |
2142 | if (result < 0) | 2142 | if (result < 0) |
2143 | goto martian_source; | 2143 | goto martian_source; |
2144 | if (result) | 2144 | if (result) |
@@ -2167,7 +2167,7 @@ brd_input: | |||
2167 | spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); | 2167 | spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); |
2168 | else { | 2168 | else { |
2169 | err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, | 2169 | err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, |
2170 | &itag); | 2170 | &itag, skb->mark); |
2171 | if (err < 0) | 2171 | if (err < 0) |
2172 | goto martian_source; | 2172 | goto martian_source; |
2173 | if (err) | 2173 | if (err) |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 4274c1cc78fd..d5e75e976513 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -1005,9 +1005,7 @@ try_again: | |||
1005 | err = ulen; | 1005 | err = ulen; |
1006 | 1006 | ||
1007 | out_free: | 1007 | out_free: |
1008 | lock_sock(sk); | 1008 | skb_free_datagram_locked(sk, skb); |
1009 | skb_free_datagram(sk, skb); | ||
1010 | release_sock(sk); | ||
1011 | out: | 1009 | out: |
1012 | return err; | 1010 | return err; |
1013 | 1011 | ||