If no flowsrc is specified on a pflow(4) interface then the src address
is determined by ip_output(). However prior to calling ip_output() pflow(4)
has already calculated the UPD pseudo-header checksum based on INADDR_ANY.
This results in a bad UPD checksum and the resulting pflow packet is
rejected by the receiver.

The diff below resolves this by calling in_selectsrc() if flowsrc is not
specified.

Nathanael

Index: if_pflow.c
===================================================================
RCS file: /cvs/src/sys/net/if_pflow.c,v
retrieving revision 1.34
diff -u -p -r1.34 if_pflow.c
--- if_pflow.c  13 Aug 2013 08:44:05 -0000      1.34
+++ if_pflow.c  30 Aug 2013 18:54:03 -0000
@@ -1512,8 +1512,37 @@ pflow_sendout_mbuf(struct pflow_softc *s
        struct ifnet    *ifp = &sc->sc_if;
 #endif
        struct ip       *ip;
+       struct in_addr   sender_ip;
        int              err;
 
+       /* Determine the sender address */
+       sender_ip = sc->sc_sender_ip;
+       if (sender_ip.s_addr == INADDR_ANY) {
+               struct sockaddr_in       sin;
+               struct sockaddr_in      *ifaddr;
+               struct route             ro;
+
+               bzero(&ro, sizeof(ro));
+               bzero(&sin, sizeof(sin));
+               sin.sin_len = sizeof(sin);
+               sin.sin_family = AF_INET;
+               sin.sin_port = sc->sc_receiver_port;
+               sin.sin_addr = sc->sc_receiver_ip;
+
+               err = 0;
+               ifaddr = in_selectsrc(&sin, &ro, 0, NULL, &err, 0);
+               if (ifaddr == NULL) {
+                       if (err == 0)
+                               err = EADDRNOTAVAIL;
+                       return err;
+               }
+
+               sender_ip = ifaddr->sin_addr;
+
+               if (ro.ro_rt)
+                       rtfree(ro.ro_rt);
+       }
+
        /* UDP Header*/
        M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
        if (m == NULL) {
@@ -1523,7 +1552,7 @@ pflow_sendout_mbuf(struct pflow_softc *s
 
        ui = mtod(m, struct udpiphdr *);
        ui->ui_pr = IPPROTO_UDP;
-       ui->ui_src = sc->sc_sender_ip;
+       ui->ui_src = sender_ip;
        ui->ui_sport = sc->sc_sender_port;
        ui->ui_dst = sc->sc_receiver_ip;
        ui->ui_dport = sc->sc_receiver_port;

Reply via email to