Skip to content

Commit 118d523

Browse files
rshearmandavem330
authored andcommitted
mpls: Enforce payload type of traffic sent using explicit NULL
RFC 4182 s2 states that if an IPv4 Explicit NULL label is the only label on the stack, then after popping the resulting packet must be treated as a IPv4 packet and forwarded based on the IPv4 header. The same is true for IPv6 Explicit NULL with an IPv6 packet following. Therefore, when installing the IPv4/IPv6 Explicit NULL label routes, add an attribute that specifies the expected payload type for use at forwarding time for determining the type of the encapsulated packet instead of inspecting the first nibble of the packet. Signed-off-by: Robert Shearman <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d74a790 commit 118d523

File tree

1 file changed

+44
-27
lines changed

1 file changed

+44
-27
lines changed

net/mpls/af_mpls.c

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,23 @@
2727
/* This maximum ha length copied from the definition of struct neighbour */
2828
#define MAX_VIA_ALEN (ALIGN(MAX_ADDR_LEN, sizeof(unsigned long)))
2929

30+
enum mpls_payload_type {
31+
MPT_UNSPEC, /* IPv4 or IPv6 */
32+
MPT_IPV4 = 4,
33+
MPT_IPV6 = 6,
34+
35+
/* Other types not implemented:
36+
* - Pseudo-wire with or without control word (RFC4385)
37+
* - GAL (RFC5586)
38+
*/
39+
};
40+
3041
struct mpls_route { /* next hop label forwarding entry */
3142
struct net_device __rcu *rt_dev;
3243
struct rcu_head rt_rcu;
3344
u32 rt_label[MAX_NEW_LABELS];
3445
u8 rt_protocol; /* routing protocol that set this entry */
46+
u8 rt_payload_type;
3547
u8 rt_labels;
3648
u8 rt_via_alen;
3749
u8 rt_via_table;
@@ -96,16 +108,8 @@ EXPORT_SYMBOL_GPL(mpls_pkt_too_big);
96108
static bool mpls_egress(struct mpls_route *rt, struct sk_buff *skb,
97109
struct mpls_entry_decoded dec)
98110
{
99-
/* RFC4385 and RFC5586 encode other packets in mpls such that
100-
* they don't conflict with the ip version number, making
101-
* decoding by examining the ip version correct in everything
102-
* except for the strangest cases.
103-
*
104-
* The strange cases if we choose to support them will require
105-
* manual configuration.
106-
*/
107-
struct iphdr *hdr4;
108-
bool success = true;
111+
enum mpls_payload_type payload_type;
112+
bool success = false;
109113

110114
/* The IPv4 code below accesses through the IPv4 header
111115
* checksum, which is 12 bytes into the packet.
@@ -120,23 +124,32 @@ static bool mpls_egress(struct mpls_route *rt, struct sk_buff *skb,
120124
if (!pskb_may_pull(skb, 12))
121125
return false;
122126

123-
/* Use ip_hdr to find the ip protocol version */
124-
hdr4 = ip_hdr(skb);
125-
if (hdr4->version == 4) {
127+
payload_type = rt->rt_payload_type;
128+
if (payload_type == MPT_UNSPEC)
129+
payload_type = ip_hdr(skb)->version;
130+
131+
switch (payload_type) {
132+
case MPT_IPV4: {
133+
struct iphdr *hdr4 = ip_hdr(skb);
126134
skb->protocol = htons(ETH_P_IP);
127135
csum_replace2(&hdr4->check,
128136
htons(hdr4->ttl << 8),
129137
htons(dec.ttl << 8));
130138
hdr4->ttl = dec.ttl;
139+
success = true;
140+
break;
131141
}
132-
else if (hdr4->version == 6) {
142+
case MPT_IPV6: {
133143
struct ipv6hdr *hdr6 = ipv6_hdr(skb);
134144
skb->protocol = htons(ETH_P_IPV6);
135145
hdr6->hop_limit = dec.ttl;
146+
success = true;
147+
break;
136148
}
137-
else
138-
/* version 0 and version 1 are used by pseudo wires */
139-
success = false;
149+
case MPT_UNSPEC:
150+
break;
151+
}
152+
140153
return success;
141154
}
142155

@@ -255,16 +268,17 @@ static const struct nla_policy rtm_mpls_policy[RTA_MAX+1] = {
255268
};
256269

257270
struct mpls_route_config {
258-
u32 rc_protocol;
259-
u32 rc_ifindex;
260-
u16 rc_via_table;
261-
u16 rc_via_alen;
262-
u8 rc_via[MAX_VIA_ALEN];
263-
u32 rc_label;
264-
u32 rc_output_labels;
265-
u32 rc_output_label[MAX_NEW_LABELS];
266-
u32 rc_nlflags;
267-
struct nl_info rc_nlinfo;
271+
u32 rc_protocol;
272+
u32 rc_ifindex;
273+
u16 rc_via_table;
274+
u16 rc_via_alen;
275+
u8 rc_via[MAX_VIA_ALEN];
276+
u32 rc_label;
277+
u32 rc_output_labels;
278+
u32 rc_output_label[MAX_NEW_LABELS];
279+
u32 rc_nlflags;
280+
enum mpls_payload_type rc_payload_type;
281+
struct nl_info rc_nlinfo;
268282
};
269283

270284
static struct mpls_route *mpls_rt_alloc(size_t alen)
@@ -493,6 +507,7 @@ static int mpls_route_add(struct mpls_route_config *cfg)
493507
rt->rt_label[i] = cfg->rc_output_label[i];
494508
rt->rt_protocol = cfg->rc_protocol;
495509
RCU_INIT_POINTER(rt->rt_dev, dev);
510+
rt->rt_payload_type = cfg->rc_payload_type;
496511
rt->rt_via_table = cfg->rc_via_table;
497512
memcpy(rt->rt_via, cfg->rc_via, cfg->rc_via_alen);
498513

@@ -1047,6 +1062,7 @@ static int resize_platform_label_table(struct net *net, size_t limit)
10471062
goto nort0;
10481063
RCU_INIT_POINTER(rt0->rt_dev, lo);
10491064
rt0->rt_protocol = RTPROT_KERNEL;
1065+
rt0->rt_payload_type = MPT_IPV4;
10501066
rt0->rt_via_table = NEIGH_LINK_TABLE;
10511067
memcpy(rt0->rt_via, lo->dev_addr, lo->addr_len);
10521068
}
@@ -1057,6 +1073,7 @@ static int resize_platform_label_table(struct net *net, size_t limit)
10571073
goto nort2;
10581074
RCU_INIT_POINTER(rt2->rt_dev, lo);
10591075
rt2->rt_protocol = RTPROT_KERNEL;
1076+
rt2->rt_payload_type = MPT_IPV6;
10601077
rt2->rt_via_table = NEIGH_LINK_TABLE;
10611078
memcpy(rt2->rt_via, lo->dev_addr, lo->addr_len);
10621079
}

0 commit comments

Comments
 (0)