Hello. I think I found a bug in divert sockets processing in pf, or maybe I'm missing something. Here is my setup, machine 192.168.250.103 is a DNS server and udp traffic coming to port 53 gets diverted to a test application. Test application is very simple, it just prints some info on the packet and reinjects it back to the kernel. Then divertion is done by IPFW, all works as expected. IPFW rule is "divert 1025 udp from any to 192.168.250.103 dst-port 53". Then I divert packets using pf rule "pass in log quick on em0 inet proto udp from any to 192.168.250.103 port 53 divert-to 127.0.0.1 port 1025", I'm starting to get a loop of the same packet comming back from divert socket again and again. If I change my sento() call to n = sendto(fd, packet, n, 0, (struct sockaddr*) &org, sizeof(org));, packet riches DNS server, but then I'm getting DNS reply in my divert socket and reply is getting looped all over again.
I've also tried sample code from OpenBSD divert man page and I'm getting same loop once again. Here is my test code: #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/udp.h> #include <arpa/inet.h> #include <errno.h> #include <err.h> #include <stdio.h> #include <stdlib.h> #include <string.h> void run (int port) { int fd; struct sockaddr_in sin; struct sockaddr_in org; int len, n, on=1; struct ip* ip; struct udphdr* udp; char *packet; packet = malloc(65536); if (packet == NULL) { warn ("malloc()"); exit(1); } ip = (struct ip*) packet; fd = socket(PF_INET, SOCK_RAW, IPPROTO_DIVERT); if (fd < 0) { warn ("socket(divert)"); exit(1); } sin.sin_len = sizeof(struct sockaddr_in); sin.sin_family = AF_INET; sin.sin_port=htons(port); sin.sin_addr.s_addr=inet_addr("127.0.0.1"); len = sizeof(struct sockaddr_in); if (bind(fd, (struct sockaddr *)&sin, len)<0) { warn("binding"); exit(1); } while (1) { len = sizeof(struct sockaddr_in); if (getsockname(fd, (struct sockaddr*) &org, &len) < 0) { warn("getsockname"); continue; } memset(packet, 0, 65536); memset(&sin, 0, sizeof(sin)); len = sizeof(sin); n = recvfrom(fd, packet, 65536, 0, (struct sockaddr*) &sin, &len); if (n < 0) { warn("recvfrom"); continue; } if (n < sizeof (struct ip)) continue; printf ("Got %d bytes from %s:%d | ", n, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); printf ("%s:%d\n", inet_ntoa(org.sin_addr), ntohs(org.sin_port)); printf ("%s -> ", inet_ntoa(ip->ip_src)); printf ("%s ", inet_ntoa(ip->ip_dst)); printf ("TTL %d, PROTO %d, hlen %d, CSUM %x\n", ip->ip_ttl, ip->ip_p, ip->ip_hl, ip->ip_sum); udp = (struct udphdr*) (packet + ip->ip_hl*4); printf ("UDP src_port %d, dst_port %d\n", ntohs(udp->uh_sport), ntohs(udp->uh_dport)); n = sendto(fd, packet, n, 0, (struct sockaddr*) &sin, sizeof(sin)); if (n < 0 ) { warn("sendto"); } } } int main(void) { run (1025); } -- Sergey Smitienko _______________________________________________ freebsd-net@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-net To unsubscribe, send any mail to "freebsd-net-unsubscr...@freebsd.org"