1 /* $Id: obsdrdr.c,v 1.66 2011/06/17 22:47:12 nanard Exp $ */
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * (c) 2006-2010 Thomas Bernard
5 * This software is subject to the conditions detailed
6 * in the LICENCE file provided within the distribution */
9 * pf rules created (with ext_if = xl1)
10 * - OpenBSD up to version 4.6 :
11 * rdr pass on xl1 inet proto udp from any to any port = 54321 \
12 * label "test label" -> 192.168.0.141 port 12345
13 * or a rdr rule + a pass rule
15 * - OpenBSD starting from version 4.7
16 * match in on xl1 inet proto udp from any to any port 54321 \
17 * label "test label" rdr-to 192.168.0.141 port 12345
19 * pass in quick on xl1 inet proto udp from any to any port 54321 \
20 * label "test label" rdr-to 192.168.0.141 port 12345
25 * - PF_ENABLE_FILTER_RULES
26 * If set, two rules are created : rdr + pass. Else a rdr/pass rule
28 * - USE_IFNAME_IN_RULES
29 * If set the interface name is set in the rule.
30 * - PFRULE_INOUT_COUNTS
31 * Must be set with OpenBSD version 3.8 and up.
32 * - PFRULE_HAS_RTABLEID
33 * Must be set with OpenBSD version 4.0 and up.
35 * Must be set with OpenBSD version 4.7 and up.
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <sys/param.h>
42 #include <netinet/in.h>
43 #include <netinet/tcp.h>
44 #include <arpa/inet.h>
46 #include <net/pf/pfvar.h>
48 #include <net/pfvar.h>
51 #include <sys/ioctl.h>
58 #include "../config.h"
60 #include "../upnpglobalvars.h"
62 /* list too keep timestamps for port mappings having a lease duration */
63 struct timestamp_entry
{
64 struct timestamp_entry
* next
;
65 unsigned int timestamp
;
70 static struct timestamp_entry
* timestamp_list
= NULL
;
73 get_timestamp(unsigned short eport
, int proto
)
75 struct timestamp_entry
* e
;
78 if(e
->eport
== eport
&& e
->protocol
== (short)proto
)
86 remove_timestamp_entry(unsigned short eport
, int proto
)
88 struct timestamp_entry
* e
;
89 struct timestamp_entry
* * p
;
93 if(e
->eport
== eport
&& e
->protocol
== (short)proto
) {
94 /* remove the entry */
105 static const char anchor_name
[] = "miniupnpd";
107 /* /dev/pf when opened */
110 /* shutdown_redirect() :
111 * close the /dev/pf device */
113 shutdown_redirect(void)
116 syslog(LOG_ERR
, "close(\"/dev/pf\"): %m");
120 /* open the device */
124 struct pf_status status
;
127 dev
= open("/dev/pf", O_RDWR
);
129 syslog(LOG_ERR
, "open(\"/dev/pf\"): %m");
132 if(ioctl(dev
, DIOCGETSTATUS
, &status
)<0) {
133 syslog(LOG_ERR
, "DIOCGETSTATUS: %m");
136 if(!status
.running
) {
137 syslog(LOG_ERR
, "pf is disabled");
146 clear_redirect_rules(void)
148 struct pfioc_trans io
;
149 struct pfioc_trans_e ioe
;
151 syslog(LOG_ERR
, "pf device is not open");
154 memset(&ioe
, 0, sizeof(ioe
));
156 io
.esize
= sizeof(ioe
);
159 ioe
.rs_num
= PF_RULESET_RDR
;
161 ioe
.type
= PF_TRANS_RULESET
;
163 strlcpy(ioe
.anchor
, anchor_name
, MAXPATHLEN
);
164 if(ioctl(dev
, DIOCXBEGIN
, &io
) < 0)
166 syslog(LOG_ERR
, "ioctl(dev, DIOCXBEGIN, ...): %m");
169 if(ioctl(dev
, DIOCXCOMMIT
, &io
) < 0)
171 syslog(LOG_ERR
, "ioctl(dev, DIOCXCOMMIT, ...): %m");
180 /* add_redirect_rule2() :
181 * create a rdr rule */
183 add_redirect_rule2(const char * ifname
,
184 const char * rhost
, unsigned short eport
,
185 const char * iaddr
, unsigned short iport
, int proto
,
186 const char * desc
, unsigned int timestamp
)
189 struct pfioc_rule pcr
;
191 struct pfioc_pooladdr pp
;
192 struct pf_pooladdr
*a
;
195 syslog(LOG_ERR
, "pf device is not open");
199 memset(&pcr
, 0, sizeof(pcr
));
200 strlcpy(pcr
.anchor
, anchor_name
, MAXPATHLEN
);
203 memset(&pp
, 0, sizeof(pp
));
204 strlcpy(pp
.anchor
, anchor_name
, MAXPATHLEN
);
205 if(ioctl(dev
, DIOCBEGINADDRS
, &pp
) < 0)
207 syslog(LOG_ERR
, "ioctl(dev, DIOCBEGINADDRS, ...): %m");
212 pcr
.pool_ticket
= pp
.ticket
;
216 pcr
.rule
.direction
= PF_IN
;
217 //pcr.rule.src.addr.type = PF_ADDR_NONE;
218 pcr
.rule
.src
.addr
.type
= PF_ADDR_ADDRMASK
;
219 pcr
.rule
.dst
.addr
.type
= PF_ADDR_ADDRMASK
;
220 pcr
.rule
.nat
.addr
.type
= PF_ADDR_NONE
;
221 pcr
.rule
.rdr
.addr
.type
= PF_ADDR_ADDRMASK
;
224 pcr
.rule
.dst
.port_op
= PF_OP_EQ
;
225 pcr
.rule
.dst
.port
[0] = htons(eport
);
226 pcr
.rule
.dst
.port
[1] = htons(eport
);
228 pcr
.rule
.action
= PF_RDR
;
229 #ifndef PF_ENABLE_FILTER_RULES
230 pcr
.rule
.natpass
= 1;
232 pcr
.rule
.natpass
= 0;
235 #ifndef PF_ENABLE_FILTER_RULES
236 pcr
.rule
.action
= PF_PASS
;
238 pcr
.rule
.action
= PF_MATCH
;
241 pcr
.rule
.af
= AF_INET
;
242 #ifdef USE_IFNAME_IN_RULES
244 strlcpy(pcr
.rule
.ifname
, ifname
, IFNAMSIZ
);
246 pcr
.rule
.proto
= proto
;
247 pcr
.rule
.log
= (GETFLAG(LOGPACKETSMASK
))?1:0; /*logpackets;*/
248 #ifdef PFRULE_HAS_RTABLEID
249 pcr
.rule
.rtableid
= -1; /* first appeared in OpenBSD 4.0 */
252 pcr
.rule
.keep_state
= PF_STATE_NORMAL
;
254 strlcpy(pcr
.rule
.tagname
, tag
, PF_TAG_NAME_SIZE
);
255 strlcpy(pcr
.rule
.label
, desc
, PF_RULE_LABEL_SIZE
);
256 if(rhost
&& rhost
[0] != '\0' && rhost
[0] != '*')
258 inet_pton(AF_INET
, rhost
, &pcr
.rule
.src
.addr
.v
.a
.addr
.v4
.s_addr
);
259 pcr
.rule
.src
.addr
.v
.a
.mask
.v4
.s_addr
= htonl(INADDR_NONE
);
262 pcr
.rule
.rpool
.proxy_port
[0] = iport
;
263 pcr
.rule
.rpool
.proxy_port
[1] = iport
;
264 TAILQ_INIT(&pcr
.rule
.rpool
.list
);
265 a
= calloc(1, sizeof(struct pf_pooladdr
));
266 inet_pton(AF_INET
, iaddr
, &a
->addr
.v
.a
.addr
.v4
.s_addr
);
267 a
->addr
.v
.a
.mask
.v4
.s_addr
= htonl(INADDR_NONE
);
268 TAILQ_INSERT_TAIL(&pcr
.rule
.rpool
.list
, a
, entries
);
270 memcpy(&pp
.addr
, a
, sizeof(struct pf_pooladdr
));
271 if(ioctl(dev
, DIOCADDADDR
, &pp
) < 0)
273 syslog(LOG_ERR
, "ioctl(dev, DIOCADDADDR, ...): %m");
279 pcr
.rule
.rdr
.proxy_port
[0] = iport
;
280 pcr
.rule
.rdr
.proxy_port
[1] = iport
;
281 inet_pton(AF_INET
, iaddr
, &pcr
.rule
.rdr
.addr
.v
.a
.addr
.v4
.s_addr
);
282 pcr
.rule
.rdr
.addr
.v
.a
.mask
.v4
.s_addr
= htonl(INADDR_NONE
);
286 pcr
.action
= PF_CHANGE_GET_TICKET
;
287 if(ioctl(dev
, DIOCCHANGERULE
, &pcr
) < 0)
289 syslog(LOG_ERR
, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_GET_TICKET: %m");
294 pcr
.action
= PF_CHANGE_ADD_TAIL
;
295 if(ioctl(dev
, DIOCCHANGERULE
, &pcr
) < 0)
297 syslog(LOG_ERR
, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_ADD_TAIL: %m");
306 if(r
== 0 && timestamp
> 0)
308 struct timestamp_entry
* tmp
;
309 tmp
= malloc(sizeof(struct timestamp_entry
));
312 tmp
->next
= timestamp_list
;
313 tmp
->timestamp
= timestamp
;
315 tmp
->protocol
= (short)proto
;
316 timestamp_list
= tmp
;
322 /* thanks to Seth Mos for this function */
324 add_filter_rule2(const char * ifname
,
325 const char * rhost
, const char * iaddr
,
326 unsigned short eport
, unsigned short iport
,
327 int proto
, const char * desc
)
329 #ifndef PF_ENABLE_FILTER_RULES
333 struct pfioc_rule pcr
;
335 struct pfioc_pooladdr pp
;
336 struct pf_pooladdr
*a
;
339 syslog(LOG_ERR
, "pf device is not open");
343 memset(&pcr
, 0, sizeof(pcr
));
344 strlcpy(pcr
.anchor
, anchor_name
, MAXPATHLEN
);
347 memset(&pp
, 0, sizeof(pp
));
348 strlcpy(pp
.anchor
, anchor_name
, MAXPATHLEN
);
349 if(ioctl(dev
, DIOCBEGINADDRS
, &pp
) < 0)
351 syslog(LOG_ERR
, "ioctl(dev, DIOCBEGINADDRS, ...): %m");
356 pcr
.pool_ticket
= pp
.ticket
;
362 pcr
.rule
.dst
.port_op
= PF_OP_EQ
;
363 pcr
.rule
.dst
.port
[0] = htons(eport
);
364 pcr
.rule
.direction
= PF_IN
;
365 pcr
.rule
.action
= PF_PASS
;
366 pcr
.rule
.af
= AF_INET
;
367 #ifdef USE_IFNAME_IN_RULES
369 strlcpy(pcr
.rule
.ifname
, ifname
, IFNAMSIZ
);
371 pcr
.rule
.proto
= proto
;
372 pcr
.rule
.quick
= (GETFLAG(PFNOQUICKRULESMASK
))?0:1;
373 pcr
.rule
.log
= (GETFLAG(LOGPACKETSMASK
))?1:0; /*logpackets;*/
374 /* see the discussion on the forum :
375 * http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=638 */
376 pcr
.rule
.flags
= TH_SYN
;
377 pcr
.rule
.flagset
= (TH_SYN
|TH_ACK
);
378 #ifdef PFRULE_HAS_RTABLEID
379 pcr
.rule
.rtableid
= -1; /* first appeared in OpenBSD 4.0 */
381 pcr
.rule
.keep_state
= 1;
382 strlcpy(pcr
.rule
.label
, desc
, PF_RULE_LABEL_SIZE
);
384 strlcpy(pcr
.rule
.qname
, queue
, PF_QNAME_SIZE
);
386 strlcpy(pcr
.rule
.tagname
, tag
, PF_TAG_NAME_SIZE
);
388 if(rhost
&& rhost
[0] != '\0' && rhost
[0] != '*')
390 inet_pton(AF_INET
, rhost
, &pcr
.rule
.src
.addr
.v
.a
.addr
.v4
.s_addr
);
391 pcr
.rule
.src
.addr
.v
.a
.mask
.v4
.s_addr
= htonl(INADDR_NONE
);
394 pcr
.rule
.rpool
.proxy_port
[0] = eport
;
395 a
= calloc(1, sizeof(struct pf_pooladdr
));
396 inet_pton(AF_INET
, iaddr
, &a
->addr
.v
.a
.addr
.v4
.s_addr
);
397 a
->addr
.v
.a
.mask
.v4
.s_addr
= htonl(INADDR_NONE
);
398 memcpy(&pp
.addr
, a
, sizeof(struct pf_pooladdr
));
399 TAILQ_INIT(&pcr
.rule
.rpool
.list
);
400 inet_pton(AF_INET
, iaddr
, &a
->addr
.v
.a
.addr
.v4
.s_addr
);
401 TAILQ_INSERT_TAIL(&pcr
.rule
.rpool
.list
, a
, entries
);
403 /* we have any - any port = # keep state label */
404 /* we want any - iaddr port = # keep state label */
405 /* memcpy(&pcr.rule.dst, a, sizeof(struct pf_pooladdr)); */
407 memcpy(&pp
.addr
, a
, sizeof(struct pf_pooladdr
));
408 strlcpy(pcr
.rule
.label
, desc
, PF_RULE_LABEL_SIZE
);
409 if(ioctl(dev
, DIOCADDADDR
, &pp
) < 0)
411 syslog(LOG_ERR
, "ioctl(dev, DIOCADDADDR, ...): %m");
420 pcr
.action
= PF_CHANGE_GET_TICKET
;
421 if(ioctl(dev
, DIOCCHANGERULE
, &pcr
) < 0)
423 syslog(LOG_ERR
, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_GET_TICKET: %m");
428 pcr
.action
= PF_CHANGE_ADD_TAIL
;
429 if(ioctl(dev
, DIOCCHANGERULE
, &pcr
) < 0)
431 syslog(LOG_ERR
, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_ADD_TAIL: %m");
444 /* get_redirect_rule()
445 * return value : 0 success (found)
446 * -1 = error or rule not found */
448 get_redirect_rule(const char * ifname
, unsigned short eport
, int proto
,
449 char * iaddr
, int iaddrlen
, unsigned short * iport
,
450 char * desc
, int desclen
, unsigned int * timestamp
,
451 u_int64_t
* packets
, u_int64_t
* bytes
)
454 struct pfioc_rule pr
;
456 struct pfioc_pooladdr pp
;
459 syslog(LOG_ERR
, "pf device is not open");
462 memset(&pr
, 0, sizeof(pr
));
463 strlcpy(pr
.anchor
, anchor_name
, MAXPATHLEN
);
465 pr
.rule
.action
= PF_RDR
;
467 if(ioctl(dev
, DIOCGETRULES
, &pr
) < 0)
469 syslog(LOG_ERR
, "ioctl(dev, DIOCGETRULES, ...): %m");
476 if(ioctl(dev
, DIOCGETRULE
, &pr
) < 0)
478 syslog(LOG_ERR
, "ioctl(dev, DIOCGETRULE): %m");
481 if( (eport
== ntohs(pr
.rule
.dst
.port
[0]))
482 && (eport
== ntohs(pr
.rule
.dst
.port
[1]))
483 && (pr
.rule
.proto
== proto
) )
486 *iport
= pr
.rule
.rpool
.proxy_port
[0];
488 *iport
= pr
.rule
.rdr
.proxy_port
[0];
491 strlcpy(desc
, pr
.rule
.label
, desclen
);
492 #ifdef PFRULE_INOUT_COUNTS
494 *packets
= pr
.rule
.packets
[0] + pr
.rule
.packets
[1];
496 *bytes
= pr
.rule
.bytes
[0] + pr
.rule
.bytes
[1];
499 *packets
= pr
.rule
.packets
;
501 *bytes
= pr
.rule
.bytes
;
504 memset(&pp
, 0, sizeof(pp
));
505 strlcpy(pp
.anchor
, anchor_name
, MAXPATHLEN
);
506 pp
.r_action
= PF_RDR
;
508 pp
.ticket
= pr
.ticket
;
509 if(ioctl(dev
, DIOCGETADDRS
, &pp
) < 0)
511 syslog(LOG_ERR
, "ioctl(dev, DIOCGETADDRS, ...): %m");
516 syslog(LOG_NOTICE
, "No address associated with pf rule");
519 pp
.nr
= 0; /* first */
520 if(ioctl(dev
, DIOCGETADDR
, &pp
) < 0)
522 syslog(LOG_ERR
, "ioctl(dev, DIOCGETADDR, ...): %m");
525 inet_ntop(AF_INET
, &pp
.addr
.addr
.v
.a
.addr
.v4
.s_addr
,
528 inet_ntop(AF_INET
, &pr
.rule
.rdr
.addr
.v
.a
.addr
.v4
.s_addr
,
532 *timestamp
= get_timestamp(eport
, proto
);
541 delete_redirect_rule(const char * ifname
, unsigned short eport
, int proto
)
544 struct pfioc_rule pr
;
546 syslog(LOG_ERR
, "pf device is not open");
549 memset(&pr
, 0, sizeof(pr
));
550 strlcpy(pr
.anchor
, anchor_name
, MAXPATHLEN
);
552 pr
.rule
.action
= PF_RDR
;
554 if(ioctl(dev
, DIOCGETRULES
, &pr
) < 0)
556 syslog(LOG_ERR
, "ioctl(dev, DIOCGETRULES, ...): %m");
563 if(ioctl(dev
, DIOCGETRULE
, &pr
) < 0)
565 syslog(LOG_ERR
, "ioctl(dev, DIOCGETRULE): %m");
568 if( (eport
== ntohs(pr
.rule
.dst
.port
[0]))
569 && (eport
== ntohs(pr
.rule
.dst
.port
[1]))
570 && (pr
.rule
.proto
== proto
) )
572 pr
.action
= PF_CHANGE_GET_TICKET
;
573 if(ioctl(dev
, DIOCCHANGERULE
, &pr
) < 0)
575 syslog(LOG_ERR
, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_GET_TICKET: %m");
578 pr
.action
= PF_CHANGE_REMOVE
;
580 if(ioctl(dev
, DIOCCHANGERULE
, &pr
) < 0)
582 syslog(LOG_ERR
, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_REMOVE: %m");
585 remove_timestamp_entry(eport
, proto
);
594 delete_filter_rule(const char * ifname
, unsigned short eport
, int proto
)
596 #ifndef PF_ENABLE_FILTER_RULES
600 struct pfioc_rule pr
;
602 syslog(LOG_ERR
, "pf device is not open");
605 memset(&pr
, 0, sizeof(pr
));
606 strlcpy(pr
.anchor
, anchor_name
, MAXPATHLEN
);
607 pr
.rule
.action
= PF_PASS
;
608 if(ioctl(dev
, DIOCGETRULES
, &pr
) < 0)
610 syslog(LOG_ERR
, "ioctl(dev, DIOCGETRULES, ...): %m");
617 if(ioctl(dev
, DIOCGETRULE
, &pr
) < 0)
619 syslog(LOG_ERR
, "ioctl(dev, DIOCGETRULE): %m");
622 if( (eport
== ntohs(pr
.rule
.dst
.port
[0]))
623 && (pr
.rule
.proto
== proto
) )
625 pr
.action
= PF_CHANGE_GET_TICKET
;
626 if(ioctl(dev
, DIOCCHANGERULE
, &pr
) < 0)
628 syslog(LOG_ERR
, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_GET_TICKET: %m");
631 pr
.action
= PF_CHANGE_REMOVE
;
633 if(ioctl(dev
, DIOCCHANGERULE
, &pr
) < 0)
635 syslog(LOG_ERR
, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_REMOVE: %m");
647 get_redirect_rule_by_index(int index
,
648 char * ifname
, unsigned short * eport
,
649 char * iaddr
, int iaddrlen
, unsigned short * iport
,
650 int * proto
, char * desc
, int desclen
,
651 char * rhost
, int rhostlen
,
652 unsigned int * timestamp
,
653 u_int64_t
* packets
, u_int64_t
* bytes
)
656 struct pfioc_rule pr
;
658 struct pfioc_pooladdr pp
;
663 syslog(LOG_ERR
, "pf device is not open");
666 memset(&pr
, 0, sizeof(pr
));
667 strlcpy(pr
.anchor
, anchor_name
, MAXPATHLEN
);
669 pr
.rule
.action
= PF_RDR
;
671 if(ioctl(dev
, DIOCGETRULES
, &pr
) < 0)
673 syslog(LOG_ERR
, "ioctl(dev, DIOCGETRULES, ...): %m");
680 if(ioctl(dev
, DIOCGETRULE
, &pr
) < 0)
682 syslog(LOG_ERR
, "ioctl(dev, DIOCGETRULE): %m");
685 *proto
= pr
.rule
.proto
;
686 *eport
= ntohs(pr
.rule
.dst
.port
[0]);
688 *iport
= pr
.rule
.rpool
.proxy_port
[0];
690 *iport
= pr
.rule
.rdr
.proxy_port
[0];
693 strlcpy(ifname
, pr
.rule
.ifname
, IFNAMSIZ
);
695 strlcpy(desc
, pr
.rule
.label
, desclen
);
696 #ifdef PFRULE_INOUT_COUNTS
698 *packets
= pr
.rule
.packets
[0] + pr
.rule
.packets
[1];
700 *bytes
= pr
.rule
.bytes
[0] + pr
.rule
.bytes
[1];
703 *packets
= pr
.rule
.packets
;
705 *bytes
= pr
.rule
.bytes
;
708 memset(&pp
, 0, sizeof(pp
));
709 strlcpy(pp
.anchor
, anchor_name
, MAXPATHLEN
);
710 pp
.r_action
= PF_RDR
;
712 pp
.ticket
= pr
.ticket
;
713 if(ioctl(dev
, DIOCGETADDRS
, &pp
) < 0)
715 syslog(LOG_ERR
, "ioctl(dev, DIOCGETADDRS, ...): %m");
720 syslog(LOG_NOTICE
, "No address associated with pf rule");
723 pp
.nr
= 0; /* first */
724 if(ioctl(dev
, DIOCGETADDR
, &pp
) < 0)
726 syslog(LOG_ERR
, "ioctl(dev, DIOCGETADDR, ...): %m");
729 inet_ntop(AF_INET
, &pp
.addr
.addr
.v
.a
.addr
.v4
.s_addr
,
732 inet_ntop(AF_INET
, &pr
.rule
.rdr
.addr
.v
.a
.addr
.v4
.s_addr
,
735 if(rhost
&& rhostlen
> 0)
737 if (pr
.rule
.src
.addr
.v
.a
.addr
.v4
.s_addr
== 0)
739 rhost
[0] = '\0'; /* empty string */
743 inet_ntop(AF_INET
, &pr
.rule
.src
.addr
.v
.a
.addr
.v4
.s_addr
,
748 *timestamp
= get_timestamp(*eport
, *proto
);
754 /* return an (malloc'ed) array of "external" port for which there is
755 * a port mapping. number is the size of the array */
757 get_portmappings_in_range(unsigned short startport
, unsigned short endport
,
758 int proto
, unsigned int * number
)
760 unsigned short * array
;
761 unsigned int capacity
;
763 unsigned short eport
;
764 struct pfioc_rule pr
;
768 syslog(LOG_ERR
, "pf device is not open");
772 array
= calloc(capacity
, sizeof(unsigned short));
775 syslog(LOG_ERR
, "get_portmappings_in_range() : calloc error");
778 memset(&pr
, 0, sizeof(pr
));
779 strlcpy(pr
.anchor
, anchor_name
, MAXPATHLEN
);
781 pr
.rule
.action
= PF_RDR
;
783 if(ioctl(dev
, DIOCGETRULES
, &pr
) < 0)
785 syslog(LOG_ERR
, "ioctl(dev, DIOCGETRULES, ...): %m");
793 if(ioctl(dev
, DIOCGETRULE
, &pr
) < 0)
795 syslog(LOG_ERR
, "ioctl(dev, DIOCGETRULE): %m");
798 eport
= ntohs(pr
.rule
.dst
.port
[0]);
799 if( (eport
== ntohs(pr
.rule
.dst
.port
[1]))
800 && (pr
.rule
.proto
== proto
)
801 && (startport
<= eport
) && (eport
<= endport
) )
803 if(*number
>= capacity
)
805 /* need to increase the capacity of the array */
807 array
= realloc(array
, sizeof(unsigned short)*capacity
);
810 syslog(LOG_ERR
, "get_portmappings_in_range() : realloc(%lu) error", sizeof(unsigned short)*capacity
);
815 array
[*number
] = eport
;
822 /* this function is only for testing */
829 struct pfioc_rule pr
;
831 struct pfioc_pooladdr pp
;
836 perror("pf dev not open");
839 memset(&pr
, 0, sizeof(pr
));
840 strlcpy(pr
.anchor
, anchor_name
, MAXPATHLEN
);
841 pr
.rule
.action
= PF_RDR
;
842 if(ioctl(dev
, DIOCGETRULES
, &pr
) < 0)
843 perror("DIOCGETRULES");
844 printf("ticket = %d, nr = %d\n", pr
.ticket
, pr
.nr
);
848 printf("-- rule %d --\n", i
);
850 if(ioctl(dev
, DIOCGETRULE
, &pr
) < 0)
851 perror("DIOCGETRULE");
852 printf(" %s %s %d:%d -> %d:%d proto %d keep_state=%d action=%d\n",
854 inet_ntop(AF_INET
, &pr
.rule
.src
.addr
.v
.a
.addr
.v4
.s_addr
, buf
, 32);
855 (int)ntohs(pr
.rule
.dst
.port
[0]),
856 (int)ntohs(pr
.rule
.dst
.port
[1]),
858 (int)pr
.rule
.rpool
.proxy_port
[0],
859 (int)pr
.rule
.rpool
.proxy_port
[1],
861 (int)pr
.rule
.rdr
.proxy_port
[0],
862 (int)pr
.rule
.rdr
.proxy_port
[1],
865 (int)pr
.rule
.keep_state
,
866 (int)pr
.rule
.action
);
867 printf(" description: \"%s\"\n", pr
.rule
.label
);
869 memset(&pp
, 0, sizeof(pp
));
870 strlcpy(pp
.anchor
, anchor_name
, MAXPATHLEN
);
871 pp
.r_action
= PF_RDR
;
873 pp
.ticket
= pr
.ticket
;
874 if(ioctl(dev
, DIOCGETADDRS
, &pp
) < 0)
875 perror("DIOCGETADDRS");
876 printf(" nb pool addr = %d ticket=%d\n", pp
.nr
, pp
.ticket
);
877 /*if(ioctl(dev, DIOCGETRULE, &pr) < 0)
878 perror("DIOCGETRULE"); */
879 pp
.nr
= 0; /* first */
880 if(ioctl(dev
, DIOCGETADDR
, &pp
) < 0)
881 perror("DIOCGETADDR");
882 /* addr.v.a.addr.v4.s_addr */
883 printf(" %s\n", inet_ntop(AF_INET
, &pp
.addr
.addr
.v
.a
.addr
.v4
.s_addr
, buf
, 32));
885 printf(" rule_flag=%08x action=%d direction=%d log=%d logif=%d "
886 "quick=%d ifnot=%d af=%d type=%d code=%d rdr.port_op=%d rdr.opts=%d\n",
887 pr
.rule
.rule_flag
, pr
.rule
.action
, pr
.rule
.direction
,
888 pr
.rule
.log
, pr
.rule
.logif
, pr
.rule
.quick
, pr
.rule
.ifnot
,
889 pr
.rule
.af
, pr
.rule
.type
, pr
.rule
.code
,
890 pr
.rule
.rdr
.port_op
, pr
.rule
.rdr
.opts
);
891 printf(" %s\n", inet_ntop(AF_INET
, &pr
.rule
.rdr
.addr
.v
.a
.addr
.v4
.s_addr
, buf
, 32));