Skip to content

Commit 013e816

Browse files
David Lebrundavem330
authored andcommitted
ipv6: sr: remove cleanup flag and fix HMAC computation
In the latest version of the IPv6 Segment Routing IETF draft [1] the cleanup flag is removed and the flags field length is shrunk from 16 bits to 8 bits. As a consequence, the input of the HMAC computation is modified in a non-backward compatible way by covering the whole octet of flags instead of only the cleanup bit. As such, if an implementation compatible with the latest draft computes the HMAC of an SRH who has other flags set to 1, then the HMAC result would differ from the current implementation. This patch carries those modifications to prevent conflict with other implementations of IPv6 SR. [1] https://tools.ietf.org/html/draft-ietf-6man-segment-routing-header-05 Signed-off-by: David Lebrun <david.lebrun@uclouvain.be> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent cafe8df commit 013e816

File tree

3 files changed

+10
-38
lines changed

3 files changed

+10
-38
lines changed

include/uapi/linux/seg6.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,12 @@ struct ipv6_sr_hdr {
2323
__u8 type;
2424
__u8 segments_left;
2525
__u8 first_segment;
26-
__u8 flag_1;
27-
__u8 flag_2;
28-
__u8 reserved;
26+
__u8 flags;
27+
__u16 reserved;
2928

3029
struct in6_addr segments[0];
3130
};
3231

33-
#define SR6_FLAG1_CLEANUP (1 << 7)
3432
#define SR6_FLAG1_PROTECTED (1 << 6)
3533
#define SR6_FLAG1_OAM (1 << 5)
3634
#define SR6_FLAG1_ALERT (1 << 4)
@@ -42,8 +40,7 @@ struct ipv6_sr_hdr {
4240
#define SR6_TLV_PADDING 4
4341
#define SR6_TLV_HMAC 5
4442

45-
#define sr_has_cleanup(srh) ((srh)->flag_1 & SR6_FLAG1_CLEANUP)
46-
#define sr_has_hmac(srh) ((srh)->flag_1 & SR6_FLAG1_HMAC)
43+
#define sr_has_hmac(srh) ((srh)->flags & SR6_FLAG1_HMAC)
4744

4845
struct sr6_tlv {
4946
__u8 type;

net/ipv6/exthdrs.c

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,6 @@ static int ipv6_srh_rcv(struct sk_buff *skb)
327327
struct ipv6_sr_hdr *hdr;
328328
struct inet6_dev *idev;
329329
struct in6_addr *addr;
330-
bool cleanup = false;
331330
int accept_seg6;
332331

333332
hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb);
@@ -351,11 +350,7 @@ static int ipv6_srh_rcv(struct sk_buff *skb)
351350
#endif
352351

353352
looped_back:
354-
if (hdr->segments_left > 0) {
355-
if (hdr->nexthdr != NEXTHDR_IPV6 && hdr->segments_left == 1 &&
356-
sr_has_cleanup(hdr))
357-
cleanup = true;
358-
} else {
353+
if (hdr->segments_left == 0) {
359354
if (hdr->nexthdr == NEXTHDR_IPV6) {
360355
int offset = (hdr->hdrlen + 1) << 3;
361356

@@ -418,21 +413,6 @@ static int ipv6_srh_rcv(struct sk_buff *skb)
418413

419414
ipv6_hdr(skb)->daddr = *addr;
420415

421-
if (cleanup) {
422-
int srhlen = (hdr->hdrlen + 1) << 3;
423-
int nh = hdr->nexthdr;
424-
425-
skb_pull_rcsum(skb, sizeof(struct ipv6hdr) + srhlen);
426-
memmove(skb_network_header(skb) + srhlen,
427-
skb_network_header(skb),
428-
(unsigned char *)hdr - skb_network_header(skb));
429-
skb->network_header += srhlen;
430-
ipv6_hdr(skb)->nexthdr = nh;
431-
ipv6_hdr(skb)->payload_len = htons(skb->len -
432-
sizeof(struct ipv6hdr));
433-
skb_push_rcsum(skb, sizeof(struct ipv6hdr));
434-
}
435-
436416
skb_dst_drop(skb);
437417

438418
ip6_route_input(skb);
@@ -453,13 +433,8 @@ static int ipv6_srh_rcv(struct sk_buff *skb)
453433
}
454434
ipv6_hdr(skb)->hop_limit--;
455435

456-
/* be sure that srh is still present before reinjecting */
457-
if (!cleanup) {
458-
skb_pull(skb, sizeof(struct ipv6hdr));
459-
goto looped_back;
460-
}
461-
skb_set_transport_header(skb, sizeof(struct ipv6hdr));
462-
IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
436+
skb_pull(skb, sizeof(struct ipv6hdr));
437+
goto looped_back;
463438
}
464439

465440
dst_input(skb);

net/ipv6/seg6_hmac.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ int seg6_hmac_compute(struct seg6_hmac_info *hinfo, struct ipv6_sr_hdr *hdr,
174174
* hash function (RadioGatun) with up to 1216 bits
175175
*/
176176

177-
/* saddr(16) + first_seg(1) + cleanup(1) + keyid(4) + seglist(16n) */
177+
/* saddr(16) + first_seg(1) + flags(1) + keyid(4) + seglist(16n) */
178178
plen = 16 + 1 + 1 + 4 + (hdr->first_segment + 1) * 16;
179179

180180
/* this limit allows for 14 segments */
@@ -186,7 +186,7 @@ int seg6_hmac_compute(struct seg6_hmac_info *hinfo, struct ipv6_sr_hdr *hdr,
186186
*
187187
* 1. Source IPv6 address (128 bits)
188188
* 2. first_segment value (8 bits)
189-
* 3. cleanup flag (8 bits: highest bit is cleanup value, others are 0)
189+
* 3. Flags (8 bits)
190190
* 4. HMAC Key ID (32 bits)
191191
* 5. All segments in the segments list (n * 128 bits)
192192
*/
@@ -202,8 +202,8 @@ int seg6_hmac_compute(struct seg6_hmac_info *hinfo, struct ipv6_sr_hdr *hdr,
202202
/* first_segment value */
203203
*off++ = hdr->first_segment;
204204

205-
/* cleanup flag */
206-
*off++ = !!(sr_has_cleanup(hdr)) << 7;
205+
/* flags */
206+
*off++ = hdr->flags;
207207

208208
/* HMAC Key ID */
209209
memcpy(off, &hmackeyid, 4);

0 commit comments

Comments
 (0)