The previous diff was a failure. This one works and makes icmp_reflect() closer
to icmp6_reflect().

Index: netinet/ip_icmp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_icmp.c,v
retrieving revision 1.181
diff -u -p -r1.181 ip_icmp.c
--- netinet/ip_icmp.c   28 Nov 2018 08:15:29 -0000      1.181
+++ netinet/ip_icmp.c   27 Dec 2018 14:50:15 -0000
@@ -676,11 +676,12 @@ freeit:
  * Reflect the ip packet back to the source
  */
 int
-icmp_reflect(struct mbuf *m, struct mbuf **op, struct in_ifaddr *ia)
+icmp_reflect(struct mbuf *m, struct mbuf **op, struct sockaddr *sa)
 {
        struct ip *ip = mtod(m, struct ip *);
        struct mbuf *opts = NULL;
        struct sockaddr_in sin;
+       struct in_ifaddr *ia = NULL;
        struct rtentry *rt = NULL;
        int optlen = (ip->ip_hl << 2) - sizeof(struct ip);
        u_int rtableid;
@@ -700,12 +701,12 @@ icmp_reflect(struct mbuf *m, struct mbuf
        m_resethdr(m);
        m->m_pkthdr.ph_rtableid = rtableid;
 
-       /*
-        * If the incoming packet was addressed directly to us,
-        * use dst as the src for the reply.  For broadcast, use
-        * the address which corresponds to the incoming interface.
-        */
-       if (ia == NULL) {
+       if (sa == NULL) {
+               /*
+                * If the incoming packet was addressed directly to us,
+                * use dst as the src for the reply.  For broadcast, use
+                * the address which corresponds to the incoming interface.
+                */
                memset(&sin, 0, sizeof(sin));
                sin.sin_len = sizeof(sin);
                sin.sin_family = AF_INET;
@@ -715,30 +716,32 @@ icmp_reflect(struct mbuf *m, struct mbuf
                if (rtisvalid(rt) &&
                    ISSET(rt->rt_flags, RTF_LOCAL|RTF_BROADCAST))
                        ia = ifatoia(rt->rt_ifa);
+               else {
+                       rtfree(rt);
+                       memset(&sin, 0, sizeof(sin));
+                       sin.sin_len = sizeof(sin);
+                       sin.sin_family = AF_INET;
+                       sin.sin_addr = ip->ip_src;
+                       sa = sintosa(&sin);
+               }
        }
-
        /*
         * The following happens if the packet was not addressed to us.
         * Use the new source address and do a route lookup. If it fails
         * drop the packet as there is no path to the host.
         */
        if (ia == NULL) {
-               rtfree(rt);
-
-               memset(&sin, 0, sizeof(sin));
-               sin.sin_len = sizeof(sin);
-               sin.sin_family = AF_INET;
-               sin.sin_addr = ip->ip_src;
-
                /* keep packet in the original virtual instance */
-               rt = rtalloc(sintosa(&sin), RT_RESOLVE, rtableid);
-               if (rt == NULL) {
+               rt = rtalloc(sa, RT_RESOLVE, rtableid);
+               if (rtisvalid(rt) &&
+                   rt->rt_ifa->ifa_addr->sa_family == AF_INET)
+                       ia = ifatoia(rt->rt_ifa);
+               else {
+                       rtfree(rt);
                        ipstat_inc(ips_noroute);
                        m_freem(m);
                        return (EHOSTUNREACH);
                }
-
-               ia = ifatoia(rt->rt_ifa);
        }
 
        ip->ip_dst = ip->ip_src;
Index: netinet/ip_icmp.h
===================================================================
RCS file: /cvs/src/sys/netinet/ip_icmp.h,v
retrieving revision 1.31
diff -u -p -r1.31 ip_icmp.h
--- netinet/ip_icmp.h   5 Nov 2018 21:50:39 -0000       1.31
+++ netinet/ip_icmp.h   27 Dec 2018 14:50:15 -0000
@@ -235,7 +235,7 @@ struct mbuf *
 void   icmp_error(struct mbuf *, int, int, u_int32_t, int);
 int    icmp_input(struct mbuf **, int *, int, int);
 void   icmp_init(void);
-int    icmp_reflect(struct mbuf *, struct mbuf **, struct in_ifaddr *);
+int    icmp_reflect(struct mbuf *, struct mbuf **, struct sockaddr *);
 void   icmp_send(struct mbuf *, struct mbuf *);
 int    icmp_sysctl(int *, u_int, void *, size_t *, void *, size_t);
 struct rtentry *
Index: netmpls/mpls_input.c
===================================================================
RCS file: /cvs/src/sys/netmpls/mpls_input.c,v
retrieving revision 1.68
diff -u -p -r1.68 mpls_input.c
--- netmpls/mpls_input.c        12 Jan 2018 06:57:56 -0000      1.68
+++ netmpls/mpls_input.c        27 Dec 2018 14:50:15 -0000
@@ -339,9 +339,7 @@ mpls_do_error(struct mbuf *m, int type, 
        struct shim_hdr stack[MPLS_INKERNEL_LOOP_MAX];
        struct sockaddr_mpls sa_mpls;
        struct sockaddr_mpls *smpls;
-       struct rtentry *rt = NULL;
        struct shim_hdr *shim;
-       struct in_ifaddr *ia;
        struct icmp *icp;
        struct ip *ip;
        int nstk, error;
@@ -380,26 +378,7 @@ mpls_do_error(struct mbuf *m, int type, 
                smpls->smpls_len = sizeof(*smpls);
                smpls->smpls_label = shim->shim_label & MPLS_LABEL_MASK;
 
-               rt = rtalloc(smplstosa(smpls), RT_RESOLVE, 0);
-               if (rt == NULL) {
-                       /* no entry for this label */
-                       m_freem(m);
-                       return (NULL);
-               }
-               if (rt->rt_ifa->ifa_addr->sa_family == AF_INET)
-                       ia = ifatoia(rt->rt_ifa);
-               else {
-                       /* XXX this needs fixing, if the MPLS is on an IP
-                        * less interface we need to find some other IP to
-                        * use as source.
-                        */
-                       rtfree(rt);
-                       m_freem(m);
-                       return (NULL);
-               }
-               /* It is safe to dereference ``ia'' iff ``rt'' is valid. */
-               error = icmp_reflect(m, NULL, ia);
-               rtfree(rt);
+               error = icmp_reflect(m, NULL, smplstosa(smpls));
                if (error)
                        return (NULL);
 

Reply via email to