Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

seg6: export get_srh() for ICMP handling

An ICMP error message can contain in its message body part of an IPv6
packet which invoked the error. Such a packet might contain a segment
router header. Export get_srh() so the ICMP code can make use of it.

Since his changes the scope of the function from local to global, add
the seg6_ prefix to keep the namespace clean. And move it into seg6.c
so it is always available, not just when IPV6_SEG6_LWTUNNEL is
enabled.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: David Ahern <dsahern@kernel.org>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Andrew Lunn and committed by
David S. Miller
fa55a7d7 e8fe9e83

+32 -31
+1
include/net/seg6.h
··· 58 58 extern void seg6_local_exit(void); 59 59 60 60 extern bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len, bool reduced); 61 + extern struct ipv6_sr_hdr *seg6_get_srh(struct sk_buff *skb, int flags); 61 62 extern int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, 62 63 int proto); 63 64 extern int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh);
+29
net/ipv6/seg6.c
··· 75 75 return true; 76 76 } 77 77 78 + struct ipv6_sr_hdr *seg6_get_srh(struct sk_buff *skb, int flags) 79 + { 80 + struct ipv6_sr_hdr *srh; 81 + int len, srhoff = 0; 82 + 83 + if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, &flags) < 0) 84 + return NULL; 85 + 86 + if (!pskb_may_pull(skb, srhoff + sizeof(*srh))) 87 + return NULL; 88 + 89 + srh = (struct ipv6_sr_hdr *)(skb->data + srhoff); 90 + 91 + len = (srh->hdrlen + 1) << 3; 92 + 93 + if (!pskb_may_pull(skb, srhoff + len)) 94 + return NULL; 95 + 96 + /* note that pskb_may_pull may change pointers in header; 97 + * for this reason it is necessary to reload them when needed. 98 + */ 99 + srh = (struct ipv6_sr_hdr *)(skb->data + srhoff); 100 + 101 + if (!seg6_validate_srh(srh, len, true)) 102 + return NULL; 103 + 104 + return srh; 105 + } 106 + 78 107 static struct genl_family seg6_genl_family; 79 108 80 109 static const struct nla_policy seg6_genl_policy[SEG6_ATTR_MAX + 1] = {
+2 -31
net/ipv6/seg6_local.c
··· 150 150 return (struct seg6_local_lwt *)lwt->data; 151 151 } 152 152 153 - static struct ipv6_sr_hdr *get_srh(struct sk_buff *skb, int flags) 154 - { 155 - struct ipv6_sr_hdr *srh; 156 - int len, srhoff = 0; 157 - 158 - if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, &flags) < 0) 159 - return NULL; 160 - 161 - if (!pskb_may_pull(skb, srhoff + sizeof(*srh))) 162 - return NULL; 163 - 164 - srh = (struct ipv6_sr_hdr *)(skb->data + srhoff); 165 - 166 - len = (srh->hdrlen + 1) << 3; 167 - 168 - if (!pskb_may_pull(skb, srhoff + len)) 169 - return NULL; 170 - 171 - /* note that pskb_may_pull may change pointers in header; 172 - * for this reason it is necessary to reload them when needed. 173 - */ 174 - srh = (struct ipv6_sr_hdr *)(skb->data + srhoff); 175 - 176 - if (!seg6_validate_srh(srh, len, true)) 177 - return NULL; 178 - 179 - return srh; 180 - } 181 - 182 153 static struct ipv6_sr_hdr *get_and_validate_srh(struct sk_buff *skb) 183 154 { 184 155 struct ipv6_sr_hdr *srh; 185 156 186 - srh = get_srh(skb, IP6_FH_F_SKIP_RH); 157 + srh = seg6_get_srh(skb, IP6_FH_F_SKIP_RH); 187 158 if (!srh) 188 159 return NULL; 189 160 ··· 171 200 struct ipv6_sr_hdr *srh; 172 201 unsigned int off = 0; 173 202 174 - srh = get_srh(skb, 0); 203 + srh = seg6_get_srh(skb, 0); 175 204 if (srh && srh->segments_left > 0) 176 205 return false; 177 206