On Tue, Jan 24, 2012 at 09:48:48PM -0500, Lawrence Teo wrote:
> 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
>
committed, thanks. i did tweak the wording a little.
for future reference for man diffs - new sentences should begin on new
lines. and the header name is EXAMPLES (plural), not EXAMPLE (singular).
thanks again,
jmc
>
> 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 ,