On Thu, Mar 17, 2022 at 12:05:16PM -0600, Theo de Raadt wrote:
> This should not be done in applications.  The kernel must do it.  It means
> the current kernel code is worng.

i think this is the right place for raw ipv4 sockets like what
ping/traceroute uses.

ipv6 looks like it already does the right thing.

Index: raw_ip.c
===================================================================
RCS file: /cvs/src/sys/netinet/raw_ip.c,v
retrieving revision 1.123
diff -u -p -r1.123 raw_ip.c
--- raw_ip.c    14 Mar 2022 22:38:43 -0000      1.123
+++ raw_ip.c    19 Mar 2022 03:40:44 -0000
@@ -222,6 +222,7 @@ int
 rip_output(struct mbuf *m, struct socket *so, struct sockaddr *dstaddr,
     struct mbuf *control)
 {
+       struct sockaddr_in *dst = satosin(dstaddr);
        struct ip *ip;
        struct inpcb *inp;
        int flags, error;
@@ -246,8 +247,8 @@ rip_output(struct mbuf *m, struct socket
                ip->ip_off = htons(0);
                ip->ip_p = inp->inp_ip.ip_p;
                ip->ip_len = htons(m->m_pkthdr.len);
-               ip->ip_src = inp->inp_laddr;
-               ip->ip_dst = satosin(dstaddr)->sin_addr;
+               ip->ip_src.s_addr = INADDR_ANY;
+               ip->ip_dst = dst->sin_addr;
                ip->ip_ttl = inp->inp_ip.ip_ttl ? inp->inp_ip.ip_ttl : MAXTTL;
        } else {
                if (m->m_pkthdr.len > IP_MAXPACKET) {
@@ -262,11 +263,23 @@ rip_output(struct mbuf *m, struct socket
                ip = mtod(m, struct ip *);
                if (ip->ip_id == 0)
                        ip->ip_id = htons(ip_randomid());
+               dst->sin_addr = ip->ip_dst;
 
                /* XXX prevent ip_output from overwriting header fields */
                flags |= IP_RAWOUTPUT;
                ipstat_inc(ips_rawout);
        }
+
+       if (ip->ip_src.s_addr == INADDR_ANY) {
+               struct in_addr *laddr;
+
+               error = in_pcbselsrc(&laddr, dst, inp);
+               if (error != 0)
+                       return (error);
+
+               ip->ip_src = *laddr;
+       }
+
 #ifdef INET6
        /*
         * A thought:  Even though raw IP shouldn't be able to set IPv6

Reply via email to