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;