Commited, thanks :).
On 8 February 2012 01:19, Lawrence Teo <l...@lteo.net> wrote:
> On Mon, Feb 06, 2012 at 09:12:35PM -0500, Lawrence Teo wrote:
>> This is a revised version of a diff that sthen@ and I worked on back in
>> May 2011. The original thread and history is at
>> http://marc.info/?t=130438996800003&r=1&w=2 if anyone is interested.
>>
>> To summarize, the current pf(4) man page's example program uses
>> DIOCNATLOOK. But Stuart pointed out in the above thread that divert-to
>> has existed since OpenBSD 4.4, so the better approach is to fetch the
>> destination address using getsockname() instead of DIOCNATLOOK. This
>> also does not require access to /dev/pf.
>>
>> In this diff, Stuart added a paragraph to the DIOCNATLOOK description in
>> the pf(4) man page to mention divert-to, while I replaced the example
>> program with one that demonstrates DIOCGETLIMIT instead. I picked
>> DIOCGETLIMIT because it will work as-is on any OpenBSD system
>> regardless of their PF rules.
>
> Here's another revision that addresses jmc@'s comments (thank you
> Jason!). It uses .Dv where appropriate and adds a missing "the" in the
> DIOCNATLOOK paragraph. The example program remains unchanged.
>
> Any further comments would be appreciated.
>
> Thank you,
> Lawrence
>
>
> Index: pf.4
> ===================================================================
> RCS file: /cvs/src/share/man/man4/pf.4,v
> retrieving revision 1.73
> diff -u -p -r1.73 pf.4
> --- pf.4 23 Dec 2011 17:00:47 -0000 1.73
> +++ pf.4 8 Feb 2012 03:11:39 -0000
> @@ -314,6 +314,22 @@ struct pfioc_natlook {
> u_int8_t direction;
> };
> .Ed
> +.Pp
> +This was primarily used to support transparent proxies with rdr-to rules.
> +New proxies should use divert-to rules instead.
> +These do not require access to the privileged
> +.Pa /dev/pf
> +device and preserve the original destination address for
> +.Xr getsockname 2 .
> +For
> +.Dv SOCK_DGRAM
> +sockets, the
> +.Xr ip 4
> +socket options
> +.Dv IP_RECVDSTADDR
> +and
> +.Dv IP_RECVDSTPORT
> +can be used to retrieve the destination address and port.
> .It Dv DIOCSETDEBUG Fa "u_int32_t *level"
> Set the debug level.
> See the
> @@ -990,68 +1006,81 @@ packet filtering device.
> .El
> .Sh EXAMPLES
> The following example demonstrates how to use the
> -.Dv DIOCNATLOOK
> -command to find the internal host/port of a NATed connection:
> +.Dv DIOCGETLIMIT
> +command to show the hard limit of a memory pool used by the packet filter:
> .Bd -literal
> #include <sys/types.h>
> #include <sys/socket.h>
> #include <sys/ioctl.h>
> #include <sys/fcntl.h>
> #include <net/if.h>
> -#include <netinet/in.h>
> #include <net/pfvar.h>
> -#include <err.h>
> #include <stdio.h>
> #include <stdlib.h>
> +#include <string.h>
> +#include <err.h>
>
> -u_int32_t
> -read_address(const char *s)
> -{
> - int a, b, c, d;
> -
> - sscanf(s, "%i.%i.%i.%i", &a, &b, &c, &d);
> - return htonl(a << 24 | b << 16 | c << 8 | d);
> -}
> +static const struct {
> + const char *name;
> + int index;
> +} pf_limits[] = {
> + { "states", PF_LIMIT_STATES },
> + { "src-nodes", PF_LIMIT_SRC_NODES },
> + { "frags", PF_LIMIT_FRAGS },
> + { "tables", PF_LIMIT_TABLES },
> + { "table-entries", PF_LIMIT_TABLE_ENTRIES },
> + { NULL, 0 }
> +};
>
> void
> -print_address(u_int32_t a)
> +usage(void)
> {
> - a = ntohl(a);
> - printf("%d.%d.%d.%d", a >> 24 & 255, a >> 16 & 255,
> - a >> 8 & 255, a & 255);
> + extern char *__progname;
> + int i;
> +
> + fprintf(stderr, "usage: %s [", __progname);
> + for (i = 0; pf_limits[i].name; i++)
> + fprintf(stderr, "%s%s", (i > 0 ? "|" : ""),
pf_limits[i].name);
> + fprintf(stderr, "]\en");
> + exit(1);
> }
>
> int
> main(int argc, char *argv[])
> {
> - struct pfioc_natlook nl;
> - int dev;
> -
> - if (argc != 5) {
> - printf("%s <gwy addr> <gwy port> <ext addr> <ext port>\en",
> - argv[0]);
> - return 1;
> + struct pfioc_limit pl;
> + int i, dev;
> + int pool_index = -1;
> +
> + if (argc != 2)
> + usage();
> +
> + for (i = 0; pf_limits[i].name; i++)
> + if (!strcmp(argv[1], pf_limits[i].name)) {
> + pool_index = pf_limits[i].index;
> + break;
> + }
> +
> + if (pool_index == -1) {
> + warnx("no such memory pool: %s", argv[1]);
> + usage();
> }
>
> dev = open("/dev/pf", O_RDWR);
> if (dev == -1)
> err(1, "open(\e"/dev/pf\e") failed");
>
> - memset(&nl, 0, sizeof(struct pfioc_natlook));
> - nl.saddr.v4.s_addr = read_address(argv[1]);
> - nl.sport = htons(atoi(argv[2]));
> - nl.daddr.v4.s_addr = read_address(argv[3]);
> - nl.dport = htons(atoi(argv[4]));
> - nl.af = AF_INET;
> - nl.proto = IPPROTO_TCP;
> - nl.direction = PF_IN;
> -
> - if (ioctl(dev, DIOCNATLOOK, &nl))
> - err(1, "DIOCNATLOOK");
> -
> - printf("internal host ");
> - print_address(nl.rsaddr.v4.s_addr);
> - printf(":%u\en", ntohs(nl.rsport));
> + bzero(&pl, sizeof(struct pfioc_limit));
> + pl.index = pool_index;
> +
> + if (ioctl(dev, DIOCGETLIMIT, &pl))
> + err(1, "DIOCGETLIMIT");
> +
> + printf("The %s memory pool has ", pf_limits[i].name);
> + if (pl.limit == UINT_MAX)
> + printf("unlimited entries.\en");
> + else
> + printf("a hard limit of %u entries.\en", pl.limit);
> return 0;
> }
> .Ed