This diff improves the example program in the divert(4) man page:

- Remove unnecessary includes
- bzero -> memset
- Better sanity checks and return value checks
- Use the tcphdr struct instead of tcpiphdr so that the program will
  work even if there are IP options
- Use more conventional variable names and buffer sizes

Also, I contributed this example section and program in 2012 and have
made other changes to the man page since then, and would like to add
myself to the copyright.

Comments/OK?


Index: divert.4
===================================================================
RCS file: /cvs/src/share/man/man4/divert.4,v
retrieving revision 1.13
diff -U5 -p -r1.13 divert.4
--- divert.4    2 Jun 2013 01:07:47 -0000       1.13
+++ divert.4    4 Jun 2014 03:59:01 -0000
@@ -1,8 +1,9 @@
 .\"     $OpenBSD: divert.4,v 1.13 2013/06/02 01:07:47 benno Exp $
 .\"
 .\" Copyright (c) 2009 Michele Marchetto <mich...@openbsd.org>
+.\" Copyright (c) 2012-2014 Lawrence Teo <l...@openbsd.org>
 .\"
 .\" Permission to use, copy, modify, and distribute this software for any
 .\" purpose with or without fee is hereby granted, provided that the above
 .\" copyright notice and this permission notice appear in all copies.
 .\"
@@ -116,16 +117,13 @@ apart from discarding invalid IP packets
 #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
 
@@ -138,11 +136,11 @@ main(int argc, char *argv[])
 
        fd = socket(AF_INET, SOCK_RAW, IPPROTO_DIVERT);
        if (fd == -1)
                err(1, "socket");
 
-       bzero(&sin, sizeof(sin));
+       memset(&sin, 0, 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);
@@ -151,46 +149,57 @@ main(int argc, char *argv[])
        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];
+               char packet[IP_MAXPACKET];
+               struct ip *ip;
+               struct tcphdr *th;
+               int hlen;
+               char src[48], dst[48];
 
-               bzero(packet, sizeof(packet));
+               memset(packet, 0, 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");
+               if (n == -1) {
+                       warn("recvfrom");
+                       continue;
+               }
+               if (n < sizeof(struct ip)) {
+                       warnx("packet is too short");
                        continue;
                }
-               if (inet_ntop(AF_INET, &ip_hdr->ip_dst, dstip,
-                   sizeof(dstip)) == NULL) {
-                       fprintf(stderr, "Invalid IPv4 destination "
-                           "packet\en");
+
+               ip = (struct ip *) packet;
+               hlen = ip->ip_hl << 2;
+               if (hlen < sizeof(struct ip) || ntohs(ip->ip_len) < hlen ||
+                   n < ntohs(ip->ip_len)) {
+                       warnx("invalid IPv4 packet");
                        continue;
                }
 
+               th = (struct tcphdr *) (packet + hlen);
+
+               if (inet_ntop(AF_INET, &ip->ip_src, src,
+                   sizeof(src)) == NULL)
+                       (void)strlcpy(src, "?", sizeof(src));
+
+               if (inet_ntop(AF_INET, &ip->ip_dst, dst,
+                   sizeof(dst)) == NULL)
+                       (void)strlcpy(dst, "?", sizeof(dst));
+
                printf("%s:%u -> %s:%u\en",
-                       srcip,
-                       ntohs(tcpip_hdr->ti_sport),
-                       dstip,
-                       ntohs(tcpip_hdr->ti_dport)
+                   src,
+                   ntohs(th->th_sport),
+                   dst,
+                   ntohs(th->th_dport)
                );
 
                n = sendto(fd, packet, n, 0, (struct sockaddr *) &sin,
                    sin_len);
+               if (n == -1)
+                       warn("sendto");
        }
 
        return 0;
 }
 .Ed

Reply via email to