__u16                   dsthao;
 #endif
        __u16                   frag_max_size;
+       __u16                   srhoff;
 
 #define IP6SKB_XFRM_TRANSFORMED        1
 #define IP6SKB_FORWARDED       2
 #define IP6SKB_HOPBYHOP        32
 #define IP6SKB_L3SLAVE         64
 #define IP6SKB_JUMBOGRAM      128
+#define IP6SKB_SEG6          256
 };
 
 #if defined(CONFIG_NET_L3_MASTER_DEV)
 
 
 extern bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len, bool reduced);
 extern struct ipv6_sr_hdr *seg6_get_srh(struct sk_buff *skb, int flags);
+extern void seg6_icmp_srh(struct sk_buff *skb, struct inet6_skb_parm *opt);
 extern int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh,
                             int proto);
 extern int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh);
 
 #include <net/protocol.h>
 #include <net/raw.h>
 #include <net/rawv6.h>
+#include <net/seg6.h>
 #include <net/transp_v6.h>
 #include <net/ip6_route.h>
 #include <net/addrconf.h>
 
 void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info)
 {
+       struct inet6_skb_parm *opt = IP6CB(skb);
        const struct inet6_protocol *ipprot;
        int inner_offset;
        __be16 frag_off;
        if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
                goto out;
 
+       seg6_icmp_srh(skb, opt);
+
        nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr;
        if (ipv6_ext_hdr(nexthdr)) {
                /* now skip over extension headers */
 
        ipprot = rcu_dereference(inet6_protos[nexthdr]);
        if (ipprot && ipprot->err_handler)
-               ipprot->err_handler(skb, NULL, type, code, inner_offset, info);
+               ipprot->err_handler(skb, opt, type, code, inner_offset, info);
 
        raw6_icmp_error(skb, nexthdr, type, code, inner_offset, info);
        return;
 
        return srh;
 }
 
+/* Determine if an ICMP invoking packet contains a segment routing
+ * header.  If it does, extract the offset to the true destination
+ * address, which is in the first segment address.
+ */
+void seg6_icmp_srh(struct sk_buff *skb, struct inet6_skb_parm *opt)
+{
+       __u16 network_header = skb->network_header;
+       struct ipv6_sr_hdr *srh;
+
+       /* Update network header to point to the invoking packet
+        * inside the ICMP packet, so we can use the seg6_get_srh()
+        * helper.
+        */
+       skb_reset_network_header(skb);
+
+       srh = seg6_get_srh(skb, 0);
+       if (!srh)
+               goto out;
+
+       if (srh->type != IPV6_SRCRT_TYPE_4)
+               goto out;
+
+       opt->flags |= IP6SKB_SEG6;
+       opt->srhoff = (unsigned char *)srh - skb->data;
+
+out:
+       /* Restore the network header back to the ICMP packet */
+       skb->network_header = network_header;
+}
+
 static struct genl_family seg6_genl_family;
 
 static const struct nla_policy seg6_genl_policy[SEG6_ATTR_MAX + 1] = {