While working with divert(4), I found that there is a lack of
documentation that describes how to actually use it.

This diff attempts to address that by adding an EXAMPLE section to the
divert(4) manpage. The example consists of a PF rule and a simple
program that uses the divert port. It is designed to be simple enough
that someone can try this on their desktop.

Comments?

Thanks,
Lawrence


Index: divert.4
===================================================================
RCS file: /cvs/src/share/man/man4/divert.4,v
retrieving revision 1.6
diff -u -p -r1.6 divert.4
--- divert.4    6 Dec 2009 18:32:43 -0000       1.6
+++ divert.4    25 Jan 2012 02:37:36 -0000
@@ -77,6 +77,94 @@ Receive and send divert socket buffer sp
 .Xr sysctl 8 .
 .Xr netstat 1
 shows information relevant to divert sockets.
+.Sh EXAMPLE
+The following PF rule queues outbound IPv4 packets to TCP port 80
+(and the return traffic) on the em0 interface to divert port 700:
+.Bd -literal -offset indent
+pass out on em0 inet proto tcp to port 80 divert-packet port 700
+.Ed
+.Pp
+The following program reads packets on divert port 700 and reinjects them
+back into the kernel. This program does not perform any processing of the
+packets, apart from discarding invalid IP packets.
+.Bd -literal
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+
+#define DIVERT_PORT 700
+
+int
+main(int argc, char *argv[])
+{
+       int fd, s;
+       struct sockaddr_in sin;
+       socklen_t sin_len;
+
+       fd = socket(AF_INET, SOCK_RAW, IPPROTO_DIVERT);
+       if (fd == -1)
+               err(1, "socket");
+
+       bzero(&sin, sizeof(sin));
+       sin.sin_family = AF_INET;
+       sin.sin_port = htons(DIVERT_PORT);
+       sin.sin_addr.s_addr = 0;
+
+       sin_len = sizeof(struct sockaddr_in);
+
+       s = bind(fd, (struct sockaddr *) &sin, sin_len);
+       if (s == -1)
+               err(1, "bind");
+
+       for (;;) {
+               ssize_t n;
+               char packet[10000];
+               struct ip *ip_hdr;
+               struct tcpiphdr *tcpip_hdr;
+               char srcip[40], dstip[40];
+
+               bzero(packet, sizeof(packet));
+               n = recvfrom(fd, packet, sizeof(packet), 0, (struct sockaddr *) 
&sin,
+                   &sin_len);
+
+               tcpip_hdr = (struct tcpiphdr *) packet;
+               ip_hdr = (struct ip *) packet;
+
+               bzero(srcip, sizeof(srcip));
+               bzero(dstip, sizeof(dstip));
+
+               if (inet_ntop(AF_INET, &ip_hdr->ip_src, srcip, sizeof(srcip)) 
== NULL) {
+                       fprintf(stderr, "Invalid IPv4 source packet\en");
+                       continue;
+               }
+               if (inet_ntop(AF_INET, &ip_hdr->ip_dst, dstip, sizeof(dstip)) 
== NULL) {
+                       fprintf(stderr, "Invalid IPv4 destination packet\en");
+                       continue;
+               }
+
+               printf("%s:%u -> %s:%u\en",
+                       srcip,
+                       ntohs(tcpip_hdr->ti_sport),
+                       dstip,
+                       ntohs(tcpip_hdr->ti_dport)
+               );
+
+               n = sendto(fd, packet, n, 0, (struct sockaddr *) &sin, sin_len);
+       }
+
+       return 0;
+}
+.Ed
 .Sh SEE ALSO
 .Xr socket 2 ,
 .Xr ip 4 ,

Reply via email to