Skip to content

Commit c1e9e01

Browse files
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next
Pablo Neira Ayuso says: ==================== Netfilter/IPVS updates for net-next The following patchset container Netfilter/IPVS update for net-next: 1) Add UDP tunnel support for ICMP errors in IPVS. Julian Anastasov says: This patchset is a followup to the commit that adds UDP/GUE tunnel: "ipvs: allow tunneling with gue encapsulation". What we do is to put tunnel real servers in hash table (patch 1), add function to lookup tunnels (patch 2) and use it to strip the embedded tunnel headers from ICMP errors (patch 3). 2) Extend xt_owner to match for supplementary groups, from Lukasz Pawelczyk. 3) Remove unused oif field in flow_offload_tuple object, from Taehee Yoo. 4) Release basechain counters from workqueue to skip synchronize_rcu() call. From Florian Westphal. 5) Replace skb_make_writable() by skb_ensure_writable(). Patchset from Florian Westphal. 6) Checksum support for gue encapsulation in IPVS, from Jacky Hu. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 0462eaa + 29930e3 commit c1e9e01

37 files changed

+389
-149
lines changed

include/linux/netfilter.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -336,11 +336,6 @@ int compat_nf_getsockopt(struct sock *sk, u_int8_t pf, int optval,
336336
char __user *opt, int *len);
337337
#endif
338338

339-
/* Call this before modifying an existing packet: ensures it is
340-
modifiable and linear to the point you care about (writable_len).
341-
Returns true or false. */
342-
int skb_make_writable(struct sk_buff *skb, unsigned int writable_len);
343-
344339
struct flowi;
345340
struct nf_queue_entry;
346341

include/net/ip_vs.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,7 @@ struct ip_vs_dest_user_kern {
603603

604604
u16 tun_type; /* tunnel type */
605605
__be16 tun_port; /* tunnel port */
606+
u16 tun_flags; /* tunnel flags */
606607
};
607608

608609

@@ -665,6 +666,7 @@ struct ip_vs_dest {
665666
atomic_t last_weight; /* server latest weight */
666667
__u16 tun_type; /* tunnel type */
667668
__be16 tun_port; /* tunnel port */
669+
__u16 tun_flags; /* tunnel flags */
668670

669671
refcount_t refcnt; /* reference counter */
670672
struct ip_vs_stats stats; /* statistics */
@@ -1404,6 +1406,9 @@ bool ip_vs_has_real_service(struct netns_ipvs *ipvs, int af, __u16 protocol,
14041406
struct ip_vs_dest *
14051407
ip_vs_find_real_service(struct netns_ipvs *ipvs, int af, __u16 protocol,
14061408
const union nf_inet_addr *daddr, __be16 dport);
1409+
struct ip_vs_dest *ip_vs_find_tunnel(struct netns_ipvs *ipvs, int af,
1410+
const union nf_inet_addr *daddr,
1411+
__be16 tun_port);
14071412

14081413
int ip_vs_use_count_inc(void);
14091414
void ip_vs_use_count_dec(void);
@@ -1497,6 +1502,9 @@ static inline int ip_vs_todrop(struct netns_ipvs *ipvs)
14971502
static inline int ip_vs_todrop(struct netns_ipvs *ipvs) { return 0; }
14981503
#endif
14991504

1505+
#define IP_VS_DFWD_METHOD(dest) (atomic_read(&(dest)->conn_flags) & \
1506+
IP_VS_CONN_F_FWD_MASK)
1507+
15001508
/* ip_vs_fwd_tag returns the forwarding tag of the connection */
15011509
#define IP_VS_FWD_METHOD(cp) (cp->flags & IP_VS_CONN_F_FWD_MASK)
15021510

include/net/netfilter/nf_flow_table.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@ struct flow_offload_tuple {
5353
u8 l4proto;
5454
u8 dir;
5555

56-
int oifidx;
57-
5856
u16 mtu;
5957

6058
struct dst_entry *dst_cache;

include/uapi/linux/ip_vs.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,11 @@ enum {
131131
IP_VS_CONN_F_TUNNEL_TYPE_MAX,
132132
};
133133

134+
/* Tunnel encapsulation flags */
135+
#define IP_VS_TUNNEL_ENCAP_FLAG_NOCSUM (0)
136+
#define IP_VS_TUNNEL_ENCAP_FLAG_CSUM (1 << 0)
137+
#define IP_VS_TUNNEL_ENCAP_FLAG_REMCSUM (1 << 1)
138+
134139
/*
135140
* The struct ip_vs_service_user and struct ip_vs_dest_user are
136141
* used to set IPVS rules through setsockopt.
@@ -403,6 +408,8 @@ enum {
403408

404409
IPVS_DEST_ATTR_TUN_PORT, /* tunnel port */
405410

411+
IPVS_DEST_ATTR_TUN_FLAGS, /* tunnel flags */
412+
406413
__IPVS_DEST_ATTR_MAX,
407414
};
408415

include/uapi/linux/netfilter/xt_owner.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
#include <linux/types.h>
66

77
enum {
8-
XT_OWNER_UID = 1 << 0,
9-
XT_OWNER_GID = 1 << 1,
10-
XT_OWNER_SOCKET = 1 << 2,
8+
XT_OWNER_UID = 1 << 0,
9+
XT_OWNER_GID = 1 << 1,
10+
XT_OWNER_SOCKET = 1 << 2,
11+
XT_OWNER_SUPPL_GROUPS = 1 << 3,
1112
};
1213

1314
struct xt_owner_match_info {

net/bridge/netfilter/ebt_dnat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ ebt_dnat_tg(struct sk_buff *skb, const struct xt_action_param *par)
2222
const struct ebt_nat_info *info = par->targinfo;
2323
struct net_device *dev;
2424

25-
if (!skb_make_writable(skb, 0))
25+
if (skb_ensure_writable(skb, ETH_ALEN))
2626
return EBT_DROP;
2727

2828
ether_addr_copy(eth_hdr(skb)->h_dest, info->mac);

net/bridge/netfilter/ebt_redirect.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ ebt_redirect_tg(struct sk_buff *skb, const struct xt_action_param *par)
2121
{
2222
const struct ebt_redirect_info *info = par->targinfo;
2323

24-
if (!skb_make_writable(skb, 0))
24+
if (skb_ensure_writable(skb, ETH_ALEN))
2525
return EBT_DROP;
2626

2727
if (xt_hooknum(par) != NF_BR_BROUTING)

net/bridge/netfilter/ebt_snat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ ebt_snat_tg(struct sk_buff *skb, const struct xt_action_param *par)
2222
{
2323
const struct ebt_nat_info *info = par->targinfo;
2424

25-
if (!skb_make_writable(skb, 0))
25+
if (skb_ensure_writable(skb, ETH_ALEN * 2))
2626
return EBT_DROP;
2727

2828
ether_addr_copy(eth_hdr(skb)->h_source, info->mac);

net/ipv4/netfilter/arpt_mangle.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ target(struct sk_buff *skb, const struct xt_action_param *par)
1717
unsigned char *arpptr;
1818
int pln, hln;
1919

20-
if (!skb_make_writable(skb, skb->len))
20+
if (skb_ensure_writable(skb, skb->len))
2121
return NF_DROP;
2222

2323
arp = arp_hdr(skb);

net/ipv4/netfilter/ipt_ECN.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ set_ect_ip(struct sk_buff *skb, const struct ipt_ECN_info *einfo)
3232

3333
if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) {
3434
__u8 oldtos;
35-
if (!skb_make_writable(skb, sizeof(struct iphdr)))
35+
if (skb_ensure_writable(skb, sizeof(struct iphdr)))
3636
return false;
3737
iph = ip_hdr(skb);
3838
oldtos = iph->tos;
@@ -61,7 +61,7 @@ set_ect_tcp(struct sk_buff *skb, const struct ipt_ECN_info *einfo)
6161
tcph->cwr == einfo->proto.tcp.cwr))
6262
return true;
6363

64-
if (!skb_make_writable(skb, ip_hdrlen(skb) + sizeof(*tcph)))
64+
if (skb_ensure_writable(skb, ip_hdrlen(skb) + sizeof(*tcph)))
6565
return false;
6666
tcph = (void *)ip_hdr(skb) + ip_hdrlen(skb);
6767

net/ipv4/netfilter/nf_nat_h323.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ static int set_addr(struct sk_buff *skb, unsigned int protoff,
5959
net_notice_ratelimited("nf_nat_h323: nf_nat_mangle_udp_packet error\n");
6060
return -1;
6161
}
62-
/* nf_nat_mangle_udp_packet uses skb_make_writable() to copy
62+
/* nf_nat_mangle_udp_packet uses skb_ensure_writable() to copy
6363
* or pull everything in a linear buffer, so we can safely
6464
* use the skb pointers now */
6565
*data = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr);

net/ipv4/netfilter/nf_nat_snmp_basic_main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
186186
return NF_DROP;
187187
}
188188

189-
if (!skb_make_writable(skb, skb->len)) {
189+
if (skb_ensure_writable(skb, skb->len)) {
190190
nf_ct_helper_log(skb, ct, "cannot mangle packet");
191191
return NF_DROP;
192192
}

net/netfilter/core.c

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -536,28 +536,6 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state,
536536
}
537537
EXPORT_SYMBOL(nf_hook_slow);
538538

539-
540-
int skb_make_writable(struct sk_buff *skb, unsigned int writable_len)
541-
{
542-
if (writable_len > skb->len)
543-
return 0;
544-
545-
/* Not exclusive use of packet? Must copy. */
546-
if (!skb_cloned(skb)) {
547-
if (writable_len <= skb_headlen(skb))
548-
return 1;
549-
} else if (skb_clone_writable(skb, writable_len))
550-
return 1;
551-
552-
if (writable_len <= skb_headlen(skb))
553-
writable_len = 0;
554-
else
555-
writable_len -= skb_headlen(skb);
556-
557-
return !!__pskb_pull_tail(skb, writable_len);
558-
}
559-
EXPORT_SYMBOL(skb_make_writable);
560-
561539
/* This needs to be compiled in any case to avoid dependencies between the
562540
* nfnetlink_queue code and nf_conntrack.
563541
*/

net/netfilter/ipvs/ip_vs_app.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff *skb,
363363
struct tcphdr *th;
364364
__u32 seq;
365365

366-
if (!skb_make_writable(skb, tcp_offset + sizeof(*th)))
366+
if (skb_ensure_writable(skb, tcp_offset + sizeof(*th)))
367367
return 0;
368368

369369
th = (struct tcphdr *)(skb_network_header(skb) + tcp_offset);
@@ -440,7 +440,7 @@ static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff *skb,
440440
struct tcphdr *th;
441441
__u32 seq;
442442

443-
if (!skb_make_writable(skb, tcp_offset + sizeof(*th)))
443+
if (skb_ensure_writable(skb, tcp_offset + sizeof(*th)))
444444
return 0;
445445

446446
th = (struct tcphdr *)(skb_network_header(skb) + tcp_offset);

net/netfilter/ipvs/ip_vs_core.c

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include <net/tcp.h>
4040
#include <net/udp.h>
4141
#include <net/icmp.h> /* for icmp_send */
42+
#include <net/gue.h>
4243
#include <net/route.h>
4344
#include <net/ip6_checksum.h>
4445
#include <net/netns/generic.h> /* net_generic() */
@@ -897,7 +898,7 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
897898
if (IPPROTO_TCP == protocol || IPPROTO_UDP == protocol ||
898899
IPPROTO_SCTP == protocol)
899900
offset += 2 * sizeof(__u16);
900-
if (!skb_make_writable(skb, offset))
901+
if (skb_ensure_writable(skb, offset))
901902
goto out;
902903

903904
#ifdef CONFIG_IP_VS_IPV6
@@ -1287,7 +1288,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
12871288

12881289
IP_VS_DBG_PKT(11, af, pp, skb, iph->off, "Outgoing packet");
12891290

1290-
if (!skb_make_writable(skb, iph->len))
1291+
if (skb_ensure_writable(skb, iph->len))
12911292
goto drop;
12921293

12931294
/* mangle the packet */
@@ -1579,6 +1580,41 @@ ip_vs_try_to_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
15791580
return 1;
15801581
}
15811582

1583+
/* Check the UDP tunnel and return its header length */
1584+
static int ipvs_udp_decap(struct netns_ipvs *ipvs, struct sk_buff *skb,
1585+
unsigned int offset, __u16 af,
1586+
const union nf_inet_addr *daddr, __u8 *proto)
1587+
{
1588+
struct udphdr _udph, *udph;
1589+
struct ip_vs_dest *dest;
1590+
1591+
udph = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
1592+
if (!udph)
1593+
goto unk;
1594+
offset += sizeof(struct udphdr);
1595+
dest = ip_vs_find_tunnel(ipvs, af, daddr, udph->dest);
1596+
if (!dest)
1597+
goto unk;
1598+
if (dest->tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) {
1599+
struct guehdr _gueh, *gueh;
1600+
1601+
gueh = skb_header_pointer(skb, offset, sizeof(_gueh), &_gueh);
1602+
if (!gueh)
1603+
goto unk;
1604+
if (gueh->control != 0 || gueh->version != 0)
1605+
goto unk;
1606+
/* Later we can support also IPPROTO_IPV6 */
1607+
if (gueh->proto_ctype != IPPROTO_IPIP)
1608+
goto unk;
1609+
*proto = gueh->proto_ctype;
1610+
return sizeof(struct udphdr) + sizeof(struct guehdr) +
1611+
(gueh->hlen << 2);
1612+
}
1613+
1614+
unk:
1615+
return 0;
1616+
}
1617+
15821618
/*
15831619
* Handle ICMP messages in the outside-to-inside direction (incoming).
15841620
* Find any that might be relevant, check against existing connections,
@@ -1598,6 +1634,7 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
15981634
struct ip_vs_proto_data *pd;
15991635
unsigned int offset, offset2, ihl, verdict;
16001636
bool ipip, new_cp = false;
1637+
union nf_inet_addr *raddr;
16011638

16021639
*related = 1;
16031640

@@ -1636,20 +1673,51 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
16361673
cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
16371674
if (cih == NULL)
16381675
return NF_ACCEPT; /* The packet looks wrong, ignore */
1676+
raddr = (union nf_inet_addr *)&cih->daddr;
16391677

16401678
/* Special case for errors for IPIP packets */
16411679
ipip = false;
16421680
if (cih->protocol == IPPROTO_IPIP) {
1681+
struct ip_vs_dest *dest;
1682+
16431683
if (unlikely(cih->frag_off & htons(IP_OFFSET)))
16441684
return NF_ACCEPT;
16451685
/* Error for our IPIP must arrive at LOCAL_IN */
16461686
if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL))
16471687
return NF_ACCEPT;
1688+
dest = ip_vs_find_tunnel(ipvs, AF_INET, raddr, 0);
1689+
/* Only for known tunnel */
1690+
if (!dest || dest->tun_type != IP_VS_CONN_F_TUNNEL_TYPE_IPIP)
1691+
return NF_ACCEPT;
16481692
offset += cih->ihl * 4;
16491693
cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
16501694
if (cih == NULL)
16511695
return NF_ACCEPT; /* The packet looks wrong, ignore */
16521696
ipip = true;
1697+
} else if (cih->protocol == IPPROTO_UDP && /* Can be UDP encap */
1698+
/* Error for our tunnel must arrive at LOCAL_IN */
1699+
(skb_rtable(skb)->rt_flags & RTCF_LOCAL)) {
1700+
__u8 iproto;
1701+
int ulen;
1702+
1703+
/* Non-first fragment has no UDP header */
1704+
if (unlikely(cih->frag_off & htons(IP_OFFSET)))
1705+
return NF_ACCEPT;
1706+
offset2 = offset + cih->ihl * 4;
1707+
ulen = ipvs_udp_decap(ipvs, skb, offset2, AF_INET, raddr,
1708+
&iproto);
1709+
if (ulen > 0) {
1710+
/* Skip IP and UDP tunnel headers */
1711+
offset = offset2 + ulen;
1712+
/* Now we should be at the original IP header */
1713+
cih = skb_header_pointer(skb, offset, sizeof(_ciph),
1714+
&_ciph);
1715+
if (cih && cih->version == 4 && cih->ihl >= 5 &&
1716+
iproto == IPPROTO_IPIP)
1717+
ipip = true;
1718+
else
1719+
return NF_ACCEPT;
1720+
}
16531721
}
16541722

16551723
pd = ip_vs_proto_data_get(ipvs, cih->protocol);

0 commit comments

Comments
 (0)