xref: /dflybsd-src/usr.sbin/ftp-proxy/filter.c (revision a14160bc65a8e6493cc912bd27de0a8a52d98af7)
1*315a7da3SJan Lentfer /*	$OpenBSD: filter.c,v 1.6 2007/08/01 09:31:41 henning Exp $ */
2a50c4a2fSJan Lentfer 
3a50c4a2fSJan Lentfer /*
4a50c4a2fSJan Lentfer  * Copyright (c) 2004, 2005 Camiel Dobbelaar, <cd@sentia.nl>
5a50c4a2fSJan Lentfer  *
6a50c4a2fSJan Lentfer  * Permission to use, copy, modify, and distribute this software for any
7a50c4a2fSJan Lentfer  * purpose with or without fee is hereby granted, provided that the above
8a50c4a2fSJan Lentfer  * copyright notice and this permission notice appear in all copies.
9a50c4a2fSJan Lentfer  *
10a50c4a2fSJan Lentfer  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11a50c4a2fSJan Lentfer  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12a50c4a2fSJan Lentfer  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13a50c4a2fSJan Lentfer  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14a50c4a2fSJan Lentfer  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15a50c4a2fSJan Lentfer  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16a50c4a2fSJan Lentfer  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17a50c4a2fSJan Lentfer  */
18a50c4a2fSJan Lentfer 
19a50c4a2fSJan Lentfer #include <sys/ioctl.h>
20a50c4a2fSJan Lentfer #include <sys/types.h>
21a50c4a2fSJan Lentfer #include <sys/socket.h>
22a50c4a2fSJan Lentfer 
23a50c4a2fSJan Lentfer #include <net/if.h>
24a50c4a2fSJan Lentfer #include <net/pf/pfvar.h>
25a50c4a2fSJan Lentfer #include <netinet/in.h>
26a50c4a2fSJan Lentfer #include <netinet/tcp.h>
27a50c4a2fSJan Lentfer #include <arpa/inet.h>
28a50c4a2fSJan Lentfer 
29a50c4a2fSJan Lentfer #include <err.h>
30a50c4a2fSJan Lentfer #include <errno.h>
31a50c4a2fSJan Lentfer #include <fcntl.h>
32a50c4a2fSJan Lentfer #include <stdio.h>
33a50c4a2fSJan Lentfer #include <string.h>
34a50c4a2fSJan Lentfer #include <unistd.h>
35a50c4a2fSJan Lentfer 
36a50c4a2fSJan Lentfer #include "filter.h"
37a50c4a2fSJan Lentfer 
38a50c4a2fSJan Lentfer /* From netinet/in.h, but only _KERNEL_ gets them. */
39a50c4a2fSJan Lentfer #define satosin(sa)	((struct sockaddr_in *)(sa))
40a50c4a2fSJan Lentfer #define satosin6(sa)	((struct sockaddr_in6 *)(sa))
41a50c4a2fSJan Lentfer 
42a50c4a2fSJan Lentfer enum { TRANS_FILTER = 0, TRANS_NAT, TRANS_RDR, TRANS_SIZE };
43a50c4a2fSJan Lentfer 
44a50c4a2fSJan Lentfer int prepare_rule(u_int32_t, int, struct sockaddr *, struct sockaddr *,
45a50c4a2fSJan Lentfer     u_int16_t);
46a50c4a2fSJan Lentfer int server_lookup4(struct sockaddr_in *, struct sockaddr_in *,
47a50c4a2fSJan Lentfer     struct sockaddr_in *);
48a50c4a2fSJan Lentfer int server_lookup6(struct sockaddr_in6 *, struct sockaddr_in6 *,
49a50c4a2fSJan Lentfer     struct sockaddr_in6 *);
50a50c4a2fSJan Lentfer 
51a50c4a2fSJan Lentfer static struct pfioc_pooladdr	pfp;
52a50c4a2fSJan Lentfer static struct pfioc_rule	pfr;
53a50c4a2fSJan Lentfer static struct pfioc_trans	pft;
54a50c4a2fSJan Lentfer static struct pfioc_trans_e	pfte[TRANS_SIZE];
55a50c4a2fSJan Lentfer static int dev, rule_log;
56*315a7da3SJan Lentfer static char *qname, *tagname;
57a50c4a2fSJan Lentfer 
58a50c4a2fSJan Lentfer int
add_filter(u_int32_t id,u_int8_t dir,struct sockaddr * src,struct sockaddr * dst,u_int16_t d_port)59a50c4a2fSJan Lentfer add_filter(u_int32_t id, u_int8_t dir, struct sockaddr *src,
60a50c4a2fSJan Lentfer     struct sockaddr *dst, u_int16_t d_port)
61a50c4a2fSJan Lentfer {
62a50c4a2fSJan Lentfer 	if (!src || !dst || !d_port) {
63a50c4a2fSJan Lentfer 		errno = EINVAL;
64a50c4a2fSJan Lentfer 		return (-1);
65a50c4a2fSJan Lentfer 	}
66a50c4a2fSJan Lentfer 
67a50c4a2fSJan Lentfer 	if (prepare_rule(id, PF_RULESET_FILTER, src, dst, d_port) == -1)
68a50c4a2fSJan Lentfer 		return (-1);
69a50c4a2fSJan Lentfer 
70a50c4a2fSJan Lentfer 	pfr.rule.direction = dir;
71a50c4a2fSJan Lentfer 	if (ioctl(dev, DIOCADDRULE, &pfr) == -1)
72a50c4a2fSJan Lentfer 		return (-1);
73a50c4a2fSJan Lentfer 
74a50c4a2fSJan Lentfer 	return (0);
75a50c4a2fSJan Lentfer }
76a50c4a2fSJan Lentfer 
77a50c4a2fSJan Lentfer int
add_nat(u_int32_t id,struct sockaddr * src,struct sockaddr * dst,u_int16_t d_port,struct sockaddr * nat,u_int16_t nat_range_low,u_int16_t nat_range_high)78a50c4a2fSJan Lentfer add_nat(u_int32_t id, struct sockaddr *src, struct sockaddr *dst,
79a50c4a2fSJan Lentfer     u_int16_t d_port, struct sockaddr *nat, u_int16_t nat_range_low,
80a50c4a2fSJan Lentfer     u_int16_t nat_range_high)
81a50c4a2fSJan Lentfer {
82a50c4a2fSJan Lentfer 	if (!src || !dst || !d_port || !nat || !nat_range_low ||
83a50c4a2fSJan Lentfer 	    (src->sa_family != nat->sa_family)) {
84a50c4a2fSJan Lentfer 		errno = EINVAL;
85a50c4a2fSJan Lentfer 		return (-1);
86a50c4a2fSJan Lentfer 	}
87a50c4a2fSJan Lentfer 
88a50c4a2fSJan Lentfer 	if (prepare_rule(id, PF_RULESET_NAT, src, dst, d_port) == -1)
89a50c4a2fSJan Lentfer 		return (-1);
90a50c4a2fSJan Lentfer 
91a50c4a2fSJan Lentfer 	if (nat->sa_family == AF_INET) {
92a50c4a2fSJan Lentfer 		memcpy(&pfp.addr.addr.v.a.addr.v4,
93a50c4a2fSJan Lentfer 		    &satosin(nat)->sin_addr.s_addr, 4);
94a50c4a2fSJan Lentfer 		memset(&pfp.addr.addr.v.a.mask.addr8, 255, 4);
95a50c4a2fSJan Lentfer 	} else {
96a50c4a2fSJan Lentfer 		memcpy(&pfp.addr.addr.v.a.addr.v6,
97a50c4a2fSJan Lentfer 		    &satosin6(nat)->sin6_addr.s6_addr, 16);
98a50c4a2fSJan Lentfer 		memset(&pfp.addr.addr.v.a.mask.addr8, 255, 16);
99a50c4a2fSJan Lentfer 	}
100a50c4a2fSJan Lentfer 	if (ioctl(dev, DIOCADDADDR, &pfp) == -1)
101a50c4a2fSJan Lentfer 		return (-1);
102a50c4a2fSJan Lentfer 
103a50c4a2fSJan Lentfer 	pfr.rule.rpool.proxy_port[0] = nat_range_low;
104a50c4a2fSJan Lentfer 	pfr.rule.rpool.proxy_port[1] = nat_range_high;
105a50c4a2fSJan Lentfer 	if (ioctl(dev, DIOCADDRULE, &pfr) == -1)
106a50c4a2fSJan Lentfer 		return (-1);
107a50c4a2fSJan Lentfer 
108a50c4a2fSJan Lentfer 	return (0);
109a50c4a2fSJan Lentfer }
110a50c4a2fSJan Lentfer 
111a50c4a2fSJan Lentfer int
add_rdr(u_int32_t id,struct sockaddr * src,struct sockaddr * dst,u_int16_t d_port,struct sockaddr * rdr,u_int16_t rdr_port)112a50c4a2fSJan Lentfer add_rdr(u_int32_t id, struct sockaddr *src, struct sockaddr *dst,
113a50c4a2fSJan Lentfer     u_int16_t d_port, struct sockaddr *rdr, u_int16_t rdr_port)
114a50c4a2fSJan Lentfer {
115a50c4a2fSJan Lentfer 	if (!src || !dst || !d_port || !rdr || !rdr_port ||
116a50c4a2fSJan Lentfer 	    (src->sa_family != rdr->sa_family)) {
117a50c4a2fSJan Lentfer 		errno = EINVAL;
118a50c4a2fSJan Lentfer 		return (-1);
119a50c4a2fSJan Lentfer 	}
120a50c4a2fSJan Lentfer 
121a50c4a2fSJan Lentfer 	if (prepare_rule(id, PF_RULESET_RDR, src, dst, d_port) == -1)
122a50c4a2fSJan Lentfer 		return (-1);
123a50c4a2fSJan Lentfer 
124a50c4a2fSJan Lentfer 	if (rdr->sa_family == AF_INET) {
125a50c4a2fSJan Lentfer 		memcpy(&pfp.addr.addr.v.a.addr.v4,
126a50c4a2fSJan Lentfer 		    &satosin(rdr)->sin_addr.s_addr, 4);
127a50c4a2fSJan Lentfer 		memset(&pfp.addr.addr.v.a.mask.addr8, 255, 4);
128a50c4a2fSJan Lentfer 	} else {
129a50c4a2fSJan Lentfer 		memcpy(&pfp.addr.addr.v.a.addr.v6,
130a50c4a2fSJan Lentfer 		    &satosin6(rdr)->sin6_addr.s6_addr, 16);
131a50c4a2fSJan Lentfer 		memset(&pfp.addr.addr.v.a.mask.addr8, 255, 16);
132a50c4a2fSJan Lentfer 	}
133a50c4a2fSJan Lentfer 	if (ioctl(dev, DIOCADDADDR, &pfp) == -1)
134a50c4a2fSJan Lentfer 		return (-1);
135a50c4a2fSJan Lentfer 
136a50c4a2fSJan Lentfer 	pfr.rule.rpool.proxy_port[0] = rdr_port;
137a50c4a2fSJan Lentfer 	if (ioctl(dev, DIOCADDRULE, &pfr) == -1)
138a50c4a2fSJan Lentfer 		return (-1);
139a50c4a2fSJan Lentfer 
140a50c4a2fSJan Lentfer 	return (0);
141a50c4a2fSJan Lentfer }
142a50c4a2fSJan Lentfer 
143a50c4a2fSJan Lentfer int
do_commit(void)144a50c4a2fSJan Lentfer do_commit(void)
145a50c4a2fSJan Lentfer {
146a50c4a2fSJan Lentfer 	if (ioctl(dev, DIOCXCOMMIT, &pft) == -1)
147a50c4a2fSJan Lentfer 		return (-1);
148a50c4a2fSJan Lentfer 
149a50c4a2fSJan Lentfer 	return (0);
150a50c4a2fSJan Lentfer }
151a50c4a2fSJan Lentfer 
152a50c4a2fSJan Lentfer int
do_rollback(void)153a50c4a2fSJan Lentfer do_rollback(void)
154a50c4a2fSJan Lentfer {
155a50c4a2fSJan Lentfer 	if (ioctl(dev, DIOCXROLLBACK, &pft) == -1)
156a50c4a2fSJan Lentfer 		return (-1);
157a50c4a2fSJan Lentfer 
158a50c4a2fSJan Lentfer 	return (0);
159a50c4a2fSJan Lentfer }
160a50c4a2fSJan Lentfer 
161a50c4a2fSJan Lentfer void
init_filter(char * opt_qname,char * opt_tagname,int opt_verbose)162*315a7da3SJan Lentfer init_filter(char *opt_qname, char *opt_tagname, int opt_verbose)
163a50c4a2fSJan Lentfer {
164a50c4a2fSJan Lentfer 	struct pf_status status;
165a50c4a2fSJan Lentfer 
166a50c4a2fSJan Lentfer 	qname = opt_qname;
167*315a7da3SJan Lentfer 	tagname = opt_tagname;
168a50c4a2fSJan Lentfer 
169a50c4a2fSJan Lentfer 	if (opt_verbose == 1)
170a50c4a2fSJan Lentfer 		rule_log = PF_LOG;
171a50c4a2fSJan Lentfer 	else if (opt_verbose == 2)
172a50c4a2fSJan Lentfer 		rule_log = PF_LOG_ALL;
173a50c4a2fSJan Lentfer 
174a50c4a2fSJan Lentfer 	dev = open("/dev/pf", O_RDWR);
175a50c4a2fSJan Lentfer 	if (dev == -1)
176a50c4a2fSJan Lentfer 		err(1, "/dev/pf");
177a50c4a2fSJan Lentfer 	if (ioctl(dev, DIOCGETSTATUS, &status) == -1)
178a50c4a2fSJan Lentfer 		err(1, "DIOCGETSTATUS");
179a50c4a2fSJan Lentfer 	if (!status.running)
180a50c4a2fSJan Lentfer 		errx(1, "pf is disabled");
181a50c4a2fSJan Lentfer }
182a50c4a2fSJan Lentfer 
183a50c4a2fSJan Lentfer int
prepare_commit(u_int32_t id)184a50c4a2fSJan Lentfer prepare_commit(u_int32_t id)
185a50c4a2fSJan Lentfer {
186a50c4a2fSJan Lentfer 	char an[PF_ANCHOR_NAME_SIZE];
187a50c4a2fSJan Lentfer 	int i;
188a50c4a2fSJan Lentfer 
189a50c4a2fSJan Lentfer 	memset(&pft, 0, sizeof pft);
190a50c4a2fSJan Lentfer 	pft.size = TRANS_SIZE;
191a50c4a2fSJan Lentfer 	pft.esize = sizeof pfte[0];
192a50c4a2fSJan Lentfer 	pft.array = pfte;
193a50c4a2fSJan Lentfer 
194a50c4a2fSJan Lentfer 	snprintf(an, PF_ANCHOR_NAME_SIZE, "%s/%d.%d", FTP_PROXY_ANCHOR,
195a50c4a2fSJan Lentfer 	    getpid(), id);
196a50c4a2fSJan Lentfer 	for (i = 0; i < TRANS_SIZE; i++) {
197a50c4a2fSJan Lentfer 		memset(&pfte[i], 0, sizeof pfte[0]);
198a50c4a2fSJan Lentfer 		strlcpy(pfte[i].anchor, an, PF_ANCHOR_NAME_SIZE);
199a50c4a2fSJan Lentfer 		switch (i) {
200a50c4a2fSJan Lentfer 		case TRANS_FILTER:
201a50c4a2fSJan Lentfer 			pfte[i].rs_num = PF_RULESET_FILTER;
202a50c4a2fSJan Lentfer 			break;
203a50c4a2fSJan Lentfer 		case TRANS_NAT:
204a50c4a2fSJan Lentfer 			pfte[i].rs_num = PF_RULESET_NAT;
205a50c4a2fSJan Lentfer 			break;
206a50c4a2fSJan Lentfer 		case TRANS_RDR:
207a50c4a2fSJan Lentfer 			pfte[i].rs_num = PF_RULESET_RDR;
208a50c4a2fSJan Lentfer 			break;
209a50c4a2fSJan Lentfer 		default:
210a50c4a2fSJan Lentfer 			errno = EINVAL;
211a50c4a2fSJan Lentfer 			return (-1);
212a50c4a2fSJan Lentfer 		}
213a50c4a2fSJan Lentfer 	}
214a50c4a2fSJan Lentfer 
215a50c4a2fSJan Lentfer 	if (ioctl(dev, DIOCXBEGIN, &pft) == -1)
216a50c4a2fSJan Lentfer 		return (-1);
217a50c4a2fSJan Lentfer 
218a50c4a2fSJan Lentfer 	return (0);
219a50c4a2fSJan Lentfer }
220a50c4a2fSJan Lentfer 
221a50c4a2fSJan Lentfer int
prepare_rule(u_int32_t id,int rs_num,struct sockaddr * src,struct sockaddr * dst,u_int16_t d_port)222a50c4a2fSJan Lentfer prepare_rule(u_int32_t id, int rs_num, struct sockaddr *src,
223a50c4a2fSJan Lentfer     struct sockaddr *dst, u_int16_t d_port)
224a50c4a2fSJan Lentfer {
225a50c4a2fSJan Lentfer 	char an[PF_ANCHOR_NAME_SIZE];
226a50c4a2fSJan Lentfer 
227a50c4a2fSJan Lentfer 	if ((src->sa_family != AF_INET && src->sa_family != AF_INET6) ||
228a50c4a2fSJan Lentfer 	    (src->sa_family != dst->sa_family)) {
229a50c4a2fSJan Lentfer 	    	errno = EPROTONOSUPPORT;
230a50c4a2fSJan Lentfer 		return (-1);
231a50c4a2fSJan Lentfer 	}
232a50c4a2fSJan Lentfer 
233a50c4a2fSJan Lentfer 	memset(&pfp, 0, sizeof pfp);
234a50c4a2fSJan Lentfer 	memset(&pfr, 0, sizeof pfr);
235a50c4a2fSJan Lentfer 	snprintf(an, PF_ANCHOR_NAME_SIZE, "%s/%d.%d", FTP_PROXY_ANCHOR,
236a50c4a2fSJan Lentfer 	    getpid(), id);
237a50c4a2fSJan Lentfer 	strlcpy(pfp.anchor, an, PF_ANCHOR_NAME_SIZE);
238a50c4a2fSJan Lentfer 	strlcpy(pfr.anchor, an, PF_ANCHOR_NAME_SIZE);
239a50c4a2fSJan Lentfer 
240a50c4a2fSJan Lentfer 	switch (rs_num) {
241a50c4a2fSJan Lentfer 	case PF_RULESET_FILTER:
242a50c4a2fSJan Lentfer 		pfr.ticket = pfte[TRANS_FILTER].ticket;
243a50c4a2fSJan Lentfer 		break;
244a50c4a2fSJan Lentfer 	case PF_RULESET_NAT:
245a50c4a2fSJan Lentfer 		pfr.ticket = pfte[TRANS_NAT].ticket;
246a50c4a2fSJan Lentfer 		break;
247a50c4a2fSJan Lentfer 	case PF_RULESET_RDR:
248a50c4a2fSJan Lentfer 		pfr.ticket = pfte[TRANS_RDR].ticket;
249a50c4a2fSJan Lentfer 		break;
250a50c4a2fSJan Lentfer 	default:
251a50c4a2fSJan Lentfer 		errno = EINVAL;
252a50c4a2fSJan Lentfer 		return (-1);
253a50c4a2fSJan Lentfer 	}
254a50c4a2fSJan Lentfer 	if (ioctl(dev, DIOCBEGINADDRS, &pfp) == -1)
255a50c4a2fSJan Lentfer 		return (-1);
256a50c4a2fSJan Lentfer 	pfr.pool_ticket = pfp.ticket;
257a50c4a2fSJan Lentfer 
258a50c4a2fSJan Lentfer 	/* Generic for all rule types. */
259a50c4a2fSJan Lentfer 	pfr.rule.af = src->sa_family;
260a50c4a2fSJan Lentfer 	pfr.rule.proto = IPPROTO_TCP;
261a50c4a2fSJan Lentfer 	pfr.rule.src.addr.type = PF_ADDR_ADDRMASK;
262a50c4a2fSJan Lentfer 	pfr.rule.dst.addr.type = PF_ADDR_ADDRMASK;
263a50c4a2fSJan Lentfer 	if (src->sa_family == AF_INET) {
264a50c4a2fSJan Lentfer 		memcpy(&pfr.rule.src.addr.v.a.addr.v4,
265a50c4a2fSJan Lentfer 		    &satosin(src)->sin_addr.s_addr, 4);
266a50c4a2fSJan Lentfer 		memset(&pfr.rule.src.addr.v.a.mask.addr8, 255, 4);
267a50c4a2fSJan Lentfer 		memcpy(&pfr.rule.dst.addr.v.a.addr.v4,
268a50c4a2fSJan Lentfer 		    &satosin(dst)->sin_addr.s_addr, 4);
269a50c4a2fSJan Lentfer 		memset(&pfr.rule.dst.addr.v.a.mask.addr8, 255, 4);
270a50c4a2fSJan Lentfer 	} else {
271a50c4a2fSJan Lentfer 		memcpy(&pfr.rule.src.addr.v.a.addr.v6,
272a50c4a2fSJan Lentfer 		    &satosin6(src)->sin6_addr.s6_addr, 16);
273a50c4a2fSJan Lentfer 		memset(&pfr.rule.src.addr.v.a.mask.addr8, 255, 16);
274a50c4a2fSJan Lentfer 		memcpy(&pfr.rule.dst.addr.v.a.addr.v6,
275a50c4a2fSJan Lentfer 		    &satosin6(dst)->sin6_addr.s6_addr, 16);
276a50c4a2fSJan Lentfer 		memset(&pfr.rule.dst.addr.v.a.mask.addr8, 255, 16);
277a50c4a2fSJan Lentfer 	}
278a50c4a2fSJan Lentfer 	pfr.rule.dst.port_op = PF_OP_EQ;
279a50c4a2fSJan Lentfer 	pfr.rule.dst.port[0] = htons(d_port);
280*315a7da3SJan Lentfer 	if (tagname != NULL)
281*315a7da3SJan Lentfer 		strlcpy(pfr.rule.tagname, tagname, sizeof pfr.rule.tagname);
282a50c4a2fSJan Lentfer 
283a50c4a2fSJan Lentfer 	switch (rs_num) {
284a50c4a2fSJan Lentfer 	case PF_RULESET_FILTER:
285a50c4a2fSJan Lentfer 		/*
286a50c4a2fSJan Lentfer 		 * pass quick [log] inet[6] proto tcp \
287a50c4a2fSJan Lentfer 		 *     from $src to $dst port = $d_port flags S/SA keep state
288a50c4a2fSJan Lentfer 		 *     (max 1) [queue qname]
289a50c4a2fSJan Lentfer 		 */
290a50c4a2fSJan Lentfer 		pfr.rule.action = PF_PASS;
291a50c4a2fSJan Lentfer 		pfr.rule.quick = 1;
292a50c4a2fSJan Lentfer 		pfr.rule.log = rule_log;
293a50c4a2fSJan Lentfer 		pfr.rule.keep_state = 1;
294a50c4a2fSJan Lentfer 		pfr.rule.flags = TH_SYN;
295a50c4a2fSJan Lentfer 		pfr.rule.flagset = (TH_SYN|TH_ACK);
296a50c4a2fSJan Lentfer 		pfr.rule.max_states = 1;
297a50c4a2fSJan Lentfer 		if (qname != NULL)
298a50c4a2fSJan Lentfer 			strlcpy(pfr.rule.qname, qname, sizeof pfr.rule.qname);
299a50c4a2fSJan Lentfer 		break;
300a50c4a2fSJan Lentfer 	case PF_RULESET_NAT:
301a50c4a2fSJan Lentfer 		/*
302a50c4a2fSJan Lentfer 		 * nat inet[6] proto tcp from $src to $dst port $d_port -> $nat
303a50c4a2fSJan Lentfer 		 */
304a50c4a2fSJan Lentfer 		pfr.rule.action = PF_NAT;
305a50c4a2fSJan Lentfer 		break;
306a50c4a2fSJan Lentfer 	case PF_RULESET_RDR:
307a50c4a2fSJan Lentfer 		/*
308a50c4a2fSJan Lentfer 		 * rdr inet[6] proto tcp from $src to $dst port $d_port -> $rdr
309a50c4a2fSJan Lentfer 		 */
310a50c4a2fSJan Lentfer 		pfr.rule.action = PF_RDR;
311a50c4a2fSJan Lentfer 		break;
312a50c4a2fSJan Lentfer 	default:
313a50c4a2fSJan Lentfer 		errno = EINVAL;
314a50c4a2fSJan Lentfer 		return (-1);
315a50c4a2fSJan Lentfer 	}
316a50c4a2fSJan Lentfer 
317a50c4a2fSJan Lentfer 	return (0);
318a50c4a2fSJan Lentfer }
319a50c4a2fSJan Lentfer 
320a50c4a2fSJan Lentfer int
server_lookup(struct sockaddr * client,struct sockaddr * proxy,struct sockaddr * server)321a50c4a2fSJan Lentfer server_lookup(struct sockaddr *client, struct sockaddr *proxy,
322a50c4a2fSJan Lentfer     struct sockaddr *server)
323a50c4a2fSJan Lentfer {
324a50c4a2fSJan Lentfer 	if (client->sa_family == AF_INET)
325a50c4a2fSJan Lentfer 		return (server_lookup4(satosin(client), satosin(proxy),
326a50c4a2fSJan Lentfer 		    satosin(server)));
327a50c4a2fSJan Lentfer 
328a50c4a2fSJan Lentfer 	if (client->sa_family == AF_INET6)
329a50c4a2fSJan Lentfer 		return (server_lookup6(satosin6(client), satosin6(proxy),
330a50c4a2fSJan Lentfer 		    satosin6(server)));
331a50c4a2fSJan Lentfer 
332a50c4a2fSJan Lentfer 	errno = EPROTONOSUPPORT;
333a50c4a2fSJan Lentfer 	return (-1);
334a50c4a2fSJan Lentfer }
335a50c4a2fSJan Lentfer 
336a50c4a2fSJan Lentfer int
server_lookup4(struct sockaddr_in * client,struct sockaddr_in * proxy,struct sockaddr_in * server)337a50c4a2fSJan Lentfer server_lookup4(struct sockaddr_in *client, struct sockaddr_in *proxy,
338a50c4a2fSJan Lentfer     struct sockaddr_in *server)
339a50c4a2fSJan Lentfer {
340a50c4a2fSJan Lentfer 	struct pfioc_natlook pnl;
341a50c4a2fSJan Lentfer 
342a50c4a2fSJan Lentfer 	memset(&pnl, 0, sizeof pnl);
343a50c4a2fSJan Lentfer 	pnl.direction = PF_OUT;
344a50c4a2fSJan Lentfer 	pnl.af = AF_INET;
345a50c4a2fSJan Lentfer 	pnl.proto = IPPROTO_TCP;
346a50c4a2fSJan Lentfer 	memcpy(&pnl.saddr.v4, &client->sin_addr.s_addr, sizeof pnl.saddr.v4);
347a50c4a2fSJan Lentfer 	memcpy(&pnl.daddr.v4, &proxy->sin_addr.s_addr, sizeof pnl.daddr.v4);
348a50c4a2fSJan Lentfer 	pnl.sport = client->sin_port;
349a50c4a2fSJan Lentfer 	pnl.dport = proxy->sin_port;
350a50c4a2fSJan Lentfer 
351a50c4a2fSJan Lentfer 	if (ioctl(dev, DIOCNATLOOK, &pnl) == -1)
352a50c4a2fSJan Lentfer 		return (-1);
353a50c4a2fSJan Lentfer 
354a50c4a2fSJan Lentfer 	memset(server, 0, sizeof(struct sockaddr_in));
355a50c4a2fSJan Lentfer 	server->sin_len = sizeof(struct sockaddr_in);
356a50c4a2fSJan Lentfer 	server->sin_family = AF_INET;
357a50c4a2fSJan Lentfer 	memcpy(&server->sin_addr.s_addr, &pnl.rdaddr.v4,
358a50c4a2fSJan Lentfer 	    sizeof server->sin_addr.s_addr);
359a50c4a2fSJan Lentfer 	server->sin_port = pnl.rdport;
360a50c4a2fSJan Lentfer 
361a50c4a2fSJan Lentfer 	return (0);
362a50c4a2fSJan Lentfer }
363a50c4a2fSJan Lentfer 
364a50c4a2fSJan Lentfer int
server_lookup6(struct sockaddr_in6 * client,struct sockaddr_in6 * proxy,struct sockaddr_in6 * server)365a50c4a2fSJan Lentfer server_lookup6(struct sockaddr_in6 *client, struct sockaddr_in6 *proxy,
366a50c4a2fSJan Lentfer     struct sockaddr_in6 *server)
367a50c4a2fSJan Lentfer {
368a50c4a2fSJan Lentfer 	struct pfioc_natlook pnl;
369a50c4a2fSJan Lentfer 
370a50c4a2fSJan Lentfer 	memset(&pnl, 0, sizeof pnl);
371a50c4a2fSJan Lentfer 	pnl.direction = PF_OUT;
372a50c4a2fSJan Lentfer 	pnl.af = AF_INET6;
373a50c4a2fSJan Lentfer 	pnl.proto = IPPROTO_TCP;
374a50c4a2fSJan Lentfer 	memcpy(&pnl.saddr.v6, &client->sin6_addr.s6_addr, sizeof pnl.saddr.v6);
375a50c4a2fSJan Lentfer 	memcpy(&pnl.daddr.v6, &proxy->sin6_addr.s6_addr, sizeof pnl.daddr.v6);
376a50c4a2fSJan Lentfer 	pnl.sport = client->sin6_port;
377a50c4a2fSJan Lentfer 	pnl.dport = proxy->sin6_port;
378a50c4a2fSJan Lentfer 
379a50c4a2fSJan Lentfer 	if (ioctl(dev, DIOCNATLOOK, &pnl) == -1)
380a50c4a2fSJan Lentfer 		return (-1);
381a50c4a2fSJan Lentfer 
382a50c4a2fSJan Lentfer 	memset(server, 0, sizeof(struct sockaddr_in6));
383a50c4a2fSJan Lentfer 	server->sin6_len = sizeof(struct sockaddr_in6);
384a50c4a2fSJan Lentfer 	server->sin6_family = AF_INET6;
385a50c4a2fSJan Lentfer 	memcpy(&server->sin6_addr.s6_addr, &pnl.rdaddr.v6,
386a50c4a2fSJan Lentfer 	    sizeof server->sin6_addr);
387a50c4a2fSJan Lentfer 	server->sin6_port = pnl.rdport;
388a50c4a2fSJan Lentfer 
389a50c4a2fSJan Lentfer 	return (0);
390a50c4a2fSJan Lentfer }
391