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=13043899683r=1w=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.423 Dec 2011 17:00:47 - 1.73
+++ pf.48 Feb 2012 03:11:39 -
@@ -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