Annotation of embedaddon/miniupnpd/pf/obsdrdr.c, revision 1.1.1.1
1.1 misho 1: /* $Id: obsdrdr.c,v 1.59 2010/05/11 16:19:26 nanard Exp $ */
2: /* MiniUPnP project
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 */
7:
8: /*
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
14: *
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
18: * or
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
21: *
22: *
23: *
24: * Macros/#defines :
25: * - PF_ENABLE_FILTER_RULES
26: * If set, two rules are created : rdr + pass. Else a rdr/pass rule
27: * is created.
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.
34: * - PF_NEWSSTYLE
35: * Must be set with OpenBSD version 4.7 and up.
36: */
37:
38: #include <sys/types.h>
39: #include <sys/socket.h>
40: #include <sys/param.h>
41: #include <net/if.h>
42: #include <netinet/in.h>
43: #include <netinet/tcp.h>
44: #include <arpa/inet.h>
45: #ifdef __DragonFly__
46: #include <net/pf/pfvar.h>
47: #else
48: #include <net/pfvar.h>
49: #endif
50: #include <fcntl.h>
51: #include <sys/ioctl.h>
52: #include <unistd.h>
53: #include <string.h>
54: #include <syslog.h>
55: #include <stdio.h>
56: #include <stdlib.h>
57:
58: #include "../config.h"
59: #include "obsdrdr.h"
60: #include "../upnpglobalvars.h"
61:
62: /* anchor name */
63: static const char anchor_name[] = "miniupnpd";
64:
65: /* /dev/pf when opened */
66: static int dev = -1;
67:
68: /* shutdown_redirect() :
69: * close the /dev/pf device */
70: void
71: shutdown_redirect(void)
72: {
73: if(close(dev)<0)
74: syslog(LOG_ERR, "close(\"/dev/pf\"): %m");
75: dev = -1;
76: }
77:
78: /* open the device */
79: int
80: init_redirect(void)
81: {
82: struct pf_status status;
83: if(dev>=0)
84: shutdown_redirect();
85: dev = open("/dev/pf", O_RDWR);
86: if(dev<0) {
87: syslog(LOG_ERR, "open(\"/dev/pf\"): %m");
88: return -1;
89: }
90: if(ioctl(dev, DIOCGETSTATUS, &status)<0) {
91: syslog(LOG_ERR, "DIOCGETSTATUS: %m");
92: return -1;
93: }
94: if(!status.running) {
95: syslog(LOG_ERR, "pf is disabled");
96: return -1;
97: }
98: return 0;
99: }
100:
101: #if TEST
102: /* for debug */
103: int
104: clear_redirect_rules(void)
105: {
106: struct pfioc_trans io;
107: struct pfioc_trans_e ioe;
108: if(dev<0) {
109: syslog(LOG_ERR, "pf device is not open");
110: return -1;
111: }
112: memset(&ioe, 0, sizeof(ioe));
113: io.size = 1;
114: io.esize = sizeof(ioe);
115: io.array = &ioe;
116: #ifndef PF_NEWSTYLE
117: ioe.rs_num = PF_RULESET_RDR;
118: #else
119: ioe.type = PF_TRANS_RULESET;
120: #endif
121: strlcpy(ioe.anchor, anchor_name, MAXPATHLEN);
122: if(ioctl(dev, DIOCXBEGIN, &io) < 0)
123: {
124: syslog(LOG_ERR, "ioctl(dev, DIOCXBEGIN, ...): %m");
125: goto error;
126: }
127: if(ioctl(dev, DIOCXCOMMIT, &io) < 0)
128: {
129: syslog(LOG_ERR, "ioctl(dev, DIOCXCOMMIT, ...): %m");
130: goto error;
131: }
132: return 0;
133: error:
134: return -1;
135: }
136: #endif
137:
138: /* add_redirect_rule2() :
139: * create a rdr rule */
140: int
141: add_redirect_rule2(const char * ifname, unsigned short eport,
142: const char * iaddr, unsigned short iport, int proto,
143: const char * desc)
144: {
145: int r;
146: struct pfioc_rule pcr;
147: #ifndef PF_NEWSTYLE
148: struct pfioc_pooladdr pp;
149: struct pf_pooladdr *a;
150: #endif
151: if(dev<0) {
152: syslog(LOG_ERR, "pf device is not open");
153: return -1;
154: }
155: r = 0;
156: memset(&pcr, 0, sizeof(pcr));
157: strlcpy(pcr.anchor, anchor_name, MAXPATHLEN);
158:
159: #ifndef PF_NEWSTYLE
160: memset(&pp, 0, sizeof(pp));
161: strlcpy(pp.anchor, anchor_name, MAXPATHLEN);
162: if(ioctl(dev, DIOCBEGINADDRS, &pp) < 0)
163: {
164: syslog(LOG_ERR, "ioctl(dev, DIOCBEGINADDRS, ...): %m");
165: r = -1;
166: }
167: else
168: {
169: pcr.pool_ticket = pp.ticket;
170: #else
171: if(1)
172: {
173: pcr.rule.direction = PF_IN;
174: //pcr.rule.src.addr.type = PF_ADDR_NONE;
175: pcr.rule.src.addr.type = PF_ADDR_ADDRMASK;
176: pcr.rule.dst.addr.type = PF_ADDR_ADDRMASK;
177: pcr.rule.nat.addr.type = PF_ADDR_NONE;
178: pcr.rule.rdr.addr.type = PF_ADDR_ADDRMASK;
179: #endif
180:
181: pcr.rule.dst.port_op = PF_OP_EQ;
182: pcr.rule.dst.port[0] = htons(eport);
183: pcr.rule.dst.port[1] = htons(eport);
184: #ifndef PF_NEWSTYLE
185: pcr.rule.action = PF_RDR;
186: #ifndef PF_ENABLE_FILTER_RULES
187: pcr.rule.natpass = 1;
188: #else
189: pcr.rule.natpass = 0;
190: #endif
191: #else
192: #ifndef PF_ENABLE_FILTER_RULES
193: pcr.rule.action = PF_PASS;
194: #else
195: pcr.rule.action = PF_MATCH;
196: #endif
197: #endif
198: pcr.rule.af = AF_INET;
199: #ifdef USE_IFNAME_IN_RULES
200: if(ifname)
201: strlcpy(pcr.rule.ifname, ifname, IFNAMSIZ);
202: #endif
203: pcr.rule.proto = proto;
204: pcr.rule.log = (GETFLAG(LOGPACKETSMASK))?1:0; /*logpackets;*/
205: #ifdef PFRULE_HAS_RTABLEID
206: pcr.rule.rtableid = -1; /* first appeared in OpenBSD 4.0 */
207: #endif
208: pcr.rule.quick = 1;
209: pcr.rule.keep_state = PF_STATE_NORMAL;
210: if(tag)
211: strlcpy(pcr.rule.tagname, tag, PF_TAG_NAME_SIZE);
212: strlcpy(pcr.rule.label, desc, PF_RULE_LABEL_SIZE);
213: #ifndef PF_NEWSTYLE
214: pcr.rule.rpool.proxy_port[0] = iport;
215: pcr.rule.rpool.proxy_port[1] = iport;
216: TAILQ_INIT(&pcr.rule.rpool.list);
217: a = calloc(1, sizeof(struct pf_pooladdr));
218: inet_pton(AF_INET, iaddr, &a->addr.v.a.addr.v4.s_addr);
219: a->addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE);
220: TAILQ_INSERT_TAIL(&pcr.rule.rpool.list, a, entries);
221:
222: memcpy(&pp.addr, a, sizeof(struct pf_pooladdr));
223: if(ioctl(dev, DIOCADDADDR, &pp) < 0)
224: {
225: syslog(LOG_ERR, "ioctl(dev, DIOCADDADDR, ...): %m");
226: r = -1;
227: }
228: else
229: {
230: #else
231: pcr.rule.rdr.proxy_port[0] = iport;
232: pcr.rule.rdr.proxy_port[1] = iport;
233: inet_pton(AF_INET, iaddr, &pcr.rule.rdr.addr.v.a.addr.v4.s_addr);
234: pcr.rule.rdr.addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE);
235: if(1)
236: {
237: #endif
238: pcr.action = PF_CHANGE_GET_TICKET;
239: if(ioctl(dev, DIOCCHANGERULE, &pcr) < 0)
240: {
241: syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_GET_TICKET: %m");
242: r = -1;
243: }
244: else
245: {
246: pcr.action = PF_CHANGE_ADD_TAIL;
247: if(ioctl(dev, DIOCCHANGERULE, &pcr) < 0)
248: {
249: syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_ADD_TAIL: %m");
250: r = -1;
251: }
252: }
253: }
254: #ifndef PF_NEWSTYLE
255: free(a);
256: #endif
257: }
258: return r;
259: }
260:
261: /* thanks to Seth Mos for this function */
262: int
263: add_filter_rule2(const char * ifname, const char * iaddr,
264: unsigned short eport, unsigned short iport,
265: int proto, const char * desc)
266: {
267: #ifndef PF_ENABLE_FILTER_RULES
268: return 0;
269: #else
270: int r;
271: struct pfioc_rule pcr;
272: #ifndef PF_NEWSTYLE
273: struct pfioc_pooladdr pp;
274: struct pf_pooladdr *a;
275: #endif
276: if(dev<0) {
277: syslog(LOG_ERR, "pf device is not open");
278: return -1;
279: }
280: r = 0;
281: memset(&pcr, 0, sizeof(pcr));
282: strlcpy(pcr.anchor, anchor_name, MAXPATHLEN);
283:
284: #ifndef PF_NEWSTYLE
285: memset(&pp, 0, sizeof(pp));
286: strlcpy(pp.anchor, anchor_name, MAXPATHLEN);
287: if(ioctl(dev, DIOCBEGINADDRS, &pp) < 0)
288: {
289: syslog(LOG_ERR, "ioctl(dev, DIOCBEGINADDRS, ...): %m");
290: r = -1;
291: }
292: else
293: {
294: pcr.pool_ticket = pp.ticket;
295: #else
296: if(1)
297: {
298: #endif
299:
300: pcr.rule.dst.port_op = PF_OP_EQ;
301: pcr.rule.dst.port[0] = htons(eport);
302: pcr.rule.direction = PF_IN;
303: pcr.rule.action = PF_PASS;
304: pcr.rule.af = AF_INET;
305: #ifdef USE_IFNAME_IN_RULES
306: if(ifname)
307: strlcpy(pcr.rule.ifname, ifname, IFNAMSIZ);
308: #endif
309: pcr.rule.proto = proto;
310: pcr.rule.quick = (GETFLAG(PFNOQUICKRULESMASK))?0:1;
311: pcr.rule.log = (GETFLAG(LOGPACKETSMASK))?1:0; /*logpackets;*/
312: /* see the discussion on the forum :
313: * http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=638 */
314: pcr.rule.flags = TH_SYN;
315: pcr.rule.flagset = (TH_SYN|TH_ACK);
316: #ifdef PFRULE_HAS_RTABLEID
317: pcr.rule.rtableid = -1; /* first appeared in OpenBSD 4.0 */
318: #endif
319: pcr.rule.keep_state = 1;
320: strlcpy(pcr.rule.label, desc, PF_RULE_LABEL_SIZE);
321: if(queue)
322: strlcpy(pcr.rule.qname, queue, PF_QNAME_SIZE);
323: if(tag)
324: strlcpy(pcr.rule.tagname, tag, PF_TAG_NAME_SIZE);
325:
326: #ifndef PF_NEWSTYLE
327: pcr.rule.rpool.proxy_port[0] = eport;
328: a = calloc(1, sizeof(struct pf_pooladdr));
329: inet_pton(AF_INET, iaddr, &a->addr.v.a.addr.v4.s_addr);
330: a->addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE);
331: memcpy(&pp.addr, a, sizeof(struct pf_pooladdr));
332: TAILQ_INIT(&pcr.rule.rpool.list);
333: inet_pton(AF_INET, iaddr, &a->addr.v.a.addr.v4.s_addr);
334: TAILQ_INSERT_TAIL(&pcr.rule.rpool.list, a, entries);
335:
336: /* we have any - any port = # keep state label */
337: /* we want any - iaddr port = # keep state label */
338: /* memcpy(&pcr.rule.dst, a, sizeof(struct pf_pooladdr)); */
339:
340: memcpy(&pp.addr, a, sizeof(struct pf_pooladdr));
341: strlcpy(pcr.rule.label, desc, PF_RULE_LABEL_SIZE);
342: if(ioctl(dev, DIOCADDADDR, &pp) < 0)
343: {
344: syslog(LOG_ERR, "ioctl(dev, DIOCADDADDR, ...): %m");
345: r = -1;
346: }
347: else
348: {
349: #else
350: if(1)
351: {
352: #endif
353: pcr.action = PF_CHANGE_GET_TICKET;
354: if(ioctl(dev, DIOCCHANGERULE, &pcr) < 0)
355: {
356: syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_GET_TICKET: %m");
357: r = -1;
358: }
359: else
360: {
361: pcr.action = PF_CHANGE_ADD_TAIL;
362: if(ioctl(dev, DIOCCHANGERULE, &pcr) < 0)
363: {
364: syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_ADD_TAIL: %m");
365: r = -1;
366: }
367: }
368: }
369: #ifndef PF_NEWSTYLE
370: free(a);
371: #endif
372: }
373: return r;
374: #endif
375: }
376:
377: /* get_redirect_rule()
378: * return value : 0 success (found)
379: * -1 = error or rule not found */
380: int
381: get_redirect_rule(const char * ifname, unsigned short eport, int proto,
382: char * iaddr, int iaddrlen, unsigned short * iport,
383: char * desc, int desclen,
384: u_int64_t * packets, u_int64_t * bytes)
385: {
386: int i, n;
387: struct pfioc_rule pr;
388: #ifndef PF_NEWSTYLE
389: struct pfioc_pooladdr pp;
390: #endif
391: if(dev<0) {
392: syslog(LOG_ERR, "pf device is not open");
393: return -1;
394: }
395: memset(&pr, 0, sizeof(pr));
396: strlcpy(pr.anchor, anchor_name, MAXPATHLEN);
397: #ifndef PF_NEWSTYLE
398: pr.rule.action = PF_RDR;
399: #endif
400: if(ioctl(dev, DIOCGETRULES, &pr) < 0)
401: {
402: syslog(LOG_ERR, "ioctl(dev, DIOCGETRULES, ...): %m");
403: goto error;
404: }
405: n = pr.nr;
406: for(i=0; i<n; i++)
407: {
408: pr.nr = i;
409: if(ioctl(dev, DIOCGETRULE, &pr) < 0)
410: {
411: syslog(LOG_ERR, "ioctl(dev, DIOCGETRULE): %m");
412: goto error;
413: }
414: if( (eport == ntohs(pr.rule.dst.port[0]))
415: && (eport == ntohs(pr.rule.dst.port[1]))
416: && (pr.rule.proto == proto) )
417: {
418: #ifndef PF_NEWSTYLE
419: *iport = pr.rule.rpool.proxy_port[0];
420: #else
421: *iport = pr.rule.rdr.proxy_port[0];
422: #endif
423: if(desc)
424: strlcpy(desc, pr.rule.label, desclen);
425: #ifdef PFRULE_INOUT_COUNTS
426: if(packets)
427: *packets = pr.rule.packets[0] + pr.rule.packets[1];
428: if(bytes)
429: *bytes = pr.rule.bytes[0] + pr.rule.bytes[1];
430: #else
431: if(packets)
432: *packets = pr.rule.packets;
433: if(bytes)
434: *bytes = pr.rule.bytes;
435: #endif
436: #ifndef PF_NEWSTYLE
437: memset(&pp, 0, sizeof(pp));
438: strlcpy(pp.anchor, anchor_name, MAXPATHLEN);
439: pp.r_action = PF_RDR;
440: pp.r_num = i;
441: pp.ticket = pr.ticket;
442: if(ioctl(dev, DIOCGETADDRS, &pp) < 0)
443: {
444: syslog(LOG_ERR, "ioctl(dev, DIOCGETADDRS, ...): %m");
445: goto error;
446: }
447: if(pp.nr != 1)
448: {
449: syslog(LOG_NOTICE, "No address associated with pf rule");
450: goto error;
451: }
452: pp.nr = 0; /* first */
453: if(ioctl(dev, DIOCGETADDR, &pp) < 0)
454: {
455: syslog(LOG_ERR, "ioctl(dev, DIOCGETADDR, ...): %m");
456: goto error;
457: }
458: inet_ntop(AF_INET, &pp.addr.addr.v.a.addr.v4.s_addr,
459: iaddr, iaddrlen);
460: #else
461: inet_ntop(AF_INET, &pr.rule.rdr.addr.v.a.addr.v4.s_addr,
462: iaddr, iaddrlen);
463: #endif
464: return 0;
465: }
466: }
467: error:
468: return -1;
469: }
470:
471: int
472: delete_redirect_rule(const char * ifname, unsigned short eport, int proto)
473: {
474: int i, n;
475: struct pfioc_rule pr;
476: if(dev<0) {
477: syslog(LOG_ERR, "pf device is not open");
478: return -1;
479: }
480: memset(&pr, 0, sizeof(pr));
481: strlcpy(pr.anchor, anchor_name, MAXPATHLEN);
482: #ifndef PF_NEWSTYLE
483: pr.rule.action = PF_RDR;
484: #endif
485: if(ioctl(dev, DIOCGETRULES, &pr) < 0)
486: {
487: syslog(LOG_ERR, "ioctl(dev, DIOCGETRULES, ...): %m");
488: goto error;
489: }
490: n = pr.nr;
491: for(i=0; i<n; i++)
492: {
493: pr.nr = i;
494: if(ioctl(dev, DIOCGETRULE, &pr) < 0)
495: {
496: syslog(LOG_ERR, "ioctl(dev, DIOCGETRULE): %m");
497: goto error;
498: }
499: if( (eport == ntohs(pr.rule.dst.port[0]))
500: && (eport == ntohs(pr.rule.dst.port[1]))
501: && (pr.rule.proto == proto) )
502: {
503: pr.action = PF_CHANGE_GET_TICKET;
504: if(ioctl(dev, DIOCCHANGERULE, &pr) < 0)
505: {
506: syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_GET_TICKET: %m");
507: goto error;
508: }
509: pr.action = PF_CHANGE_REMOVE;
510: pr.nr = i;
511: if(ioctl(dev, DIOCCHANGERULE, &pr) < 0)
512: {
513: syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_REMOVE: %m");
514: goto error;
515: }
516: return 0;
517: }
518: }
519: error:
520: return -1;
521: }
522:
523: int
524: delete_filter_rule(const char * ifname, unsigned short eport, int proto)
525: {
526: #ifndef PF_ENABLE_FILTER_RULES
527: return 0;
528: #else
529: int i, n;
530: struct pfioc_rule pr;
531: if(dev<0) {
532: syslog(LOG_ERR, "pf device is not open");
533: return -1;
534: }
535: memset(&pr, 0, sizeof(pr));
536: strlcpy(pr.anchor, anchor_name, MAXPATHLEN);
537: pr.rule.action = PF_PASS;
538: if(ioctl(dev, DIOCGETRULES, &pr) < 0)
539: {
540: syslog(LOG_ERR, "ioctl(dev, DIOCGETRULES, ...): %m");
541: goto error;
542: }
543: n = pr.nr;
544: for(i=0; i<n; i++)
545: {
546: pr.nr = i;
547: if(ioctl(dev, DIOCGETRULE, &pr) < 0)
548: {
549: syslog(LOG_ERR, "ioctl(dev, DIOCGETRULE): %m");
550: goto error;
551: }
552: if( (eport == ntohs(pr.rule.dst.port[0]))
553: && (pr.rule.proto == proto) )
554: {
555: pr.action = PF_CHANGE_GET_TICKET;
556: if(ioctl(dev, DIOCCHANGERULE, &pr) < 0)
557: {
558: syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_GET_TICKET: %m");
559: goto error;
560: }
561: pr.action = PF_CHANGE_REMOVE;
562: pr.nr = i;
563: if(ioctl(dev, DIOCCHANGERULE, &pr) < 0)
564: {
565: syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_REMOVE: %m");
566: goto error;
567: }
568: return 0;
569: }
570: }
571: error:
572: return -1;
573: #endif
574: }
575:
576: int
577: get_redirect_rule_by_index(int index,
578: char * ifname, unsigned short * eport,
579: char * iaddr, int iaddrlen, unsigned short * iport,
580: int * proto, char * desc, int desclen,
581: u_int64_t * packets, u_int64_t * bytes)
582: {
583: int n;
584: struct pfioc_rule pr;
585: #ifndef PF_NEWSTYLE
586: struct pfioc_pooladdr pp;
587: #endif
588: if(index < 0)
589: return -1;
590: if(dev<0) {
591: syslog(LOG_ERR, "pf device is not open");
592: return -1;
593: }
594: memset(&pr, 0, sizeof(pr));
595: strlcpy(pr.anchor, anchor_name, MAXPATHLEN);
596: #ifndef PF_NEWSTYLE
597: pr.rule.action = PF_RDR;
598: #endif
599: if(ioctl(dev, DIOCGETRULES, &pr) < 0)
600: {
601: syslog(LOG_ERR, "ioctl(dev, DIOCGETRULES, ...): %m");
602: goto error;
603: }
604: n = pr.nr;
605: if(index >= n)
606: goto error;
607: pr.nr = index;
608: if(ioctl(dev, DIOCGETRULE, &pr) < 0)
609: {
610: syslog(LOG_ERR, "ioctl(dev, DIOCGETRULE): %m");
611: goto error;
612: }
613: *proto = pr.rule.proto;
614: *eport = ntohs(pr.rule.dst.port[0]);
615: #ifndef PF_NEWSTYLE
616: *iport = pr.rule.rpool.proxy_port[0];
617: #else
618: *iport = pr.rule.rdr.proxy_port[0];
619: #endif
620: if(ifname)
621: strlcpy(ifname, pr.rule.ifname, IFNAMSIZ);
622: if(desc)
623: strlcpy(desc, pr.rule.label, desclen);
624: #ifdef PFRULE_INOUT_COUNTS
625: if(packets)
626: *packets = pr.rule.packets[0] + pr.rule.packets[1];
627: if(bytes)
628: *bytes = pr.rule.bytes[0] + pr.rule.bytes[1];
629: #else
630: if(packets)
631: *packets = pr.rule.packets;
632: if(bytes)
633: *bytes = pr.rule.bytes;
634: #endif
635: #ifndef PF_NEWSTYLE
636: memset(&pp, 0, sizeof(pp));
637: strlcpy(pp.anchor, anchor_name, MAXPATHLEN);
638: pp.r_action = PF_RDR;
639: pp.r_num = index;
640: pp.ticket = pr.ticket;
641: if(ioctl(dev, DIOCGETADDRS, &pp) < 0)
642: {
643: syslog(LOG_ERR, "ioctl(dev, DIOCGETADDRS, ...): %m");
644: goto error;
645: }
646: if(pp.nr != 1)
647: {
648: syslog(LOG_NOTICE, "No address associated with pf rule");
649: goto error;
650: }
651: pp.nr = 0; /* first */
652: if(ioctl(dev, DIOCGETADDR, &pp) < 0)
653: {
654: syslog(LOG_ERR, "ioctl(dev, DIOCGETADDR, ...): %m");
655: goto error;
656: }
657: inet_ntop(AF_INET, &pp.addr.addr.v.a.addr.v4.s_addr,
658: iaddr, iaddrlen);
659: #else
660: inet_ntop(AF_INET, &pr.rule.rdr.addr.v.a.addr.v4.s_addr,
661: iaddr, iaddrlen);
662: #endif
663: return 0;
664: error:
665: return -1;
666: }
667:
668: /* this function is only for testing */
669: #if TEST
670: void
671: list_rules(void)
672: {
673: char buf[32];
674: int i, n;
675: struct pfioc_rule pr;
676: #ifndef PF_NEWSTYLE
677: struct pfioc_pooladdr pp;
678: #endif
679:
680: if(dev<0)
681: {
682: perror("pf dev not open");
683: return ;
684: }
685: memset(&pr, 0, sizeof(pr));
686: strlcpy(pr.anchor, anchor_name, MAXPATHLEN);
687: pr.rule.action = PF_RDR;
688: if(ioctl(dev, DIOCGETRULES, &pr) < 0)
689: perror("DIOCGETRULES");
690: printf("ticket = %d, nr = %d\n", pr.ticket, pr.nr);
691: n = pr.nr;
692: for(i=0; i<n; i++)
693: {
694: printf("-- rule %d --\n", i);
695: pr.nr = i;
696: if(ioctl(dev, DIOCGETRULE, &pr) < 0)
697: perror("DIOCGETRULE");
698: printf(" %s %d:%d -> %d:%d proto %d keep_state=%d action=%d\n",
699: pr.rule.ifname,
700: (int)ntohs(pr.rule.dst.port[0]),
701: (int)ntohs(pr.rule.dst.port[1]),
702: #ifndef PF_NEWSTYLE
703: (int)pr.rule.rpool.proxy_port[0],
704: (int)pr.rule.rpool.proxy_port[1],
705: #else
706: (int)pr.rule.rdr.proxy_port[0],
707: (int)pr.rule.rdr.proxy_port[1],
708: #endif
709: (int)pr.rule.proto,
710: (int)pr.rule.keep_state,
711: (int)pr.rule.action);
712: printf(" description: \"%s\"\n", pr.rule.label);
713: #ifndef PF_NEWSTYLE
714: memset(&pp, 0, sizeof(pp));
715: strlcpy(pp.anchor, anchor_name, MAXPATHLEN);
716: pp.r_action = PF_RDR;
717: pp.r_num = i;
718: pp.ticket = pr.ticket;
719: if(ioctl(dev, DIOCGETADDRS, &pp) < 0)
720: perror("DIOCGETADDRS");
721: printf(" nb pool addr = %d ticket=%d\n", pp.nr, pp.ticket);
722: /*if(ioctl(dev, DIOCGETRULE, &pr) < 0)
723: perror("DIOCGETRULE"); */
724: pp.nr = 0; /* first */
725: if(ioctl(dev, DIOCGETADDR, &pp) < 0)
726: perror("DIOCGETADDR");
727: /* addr.v.a.addr.v4.s_addr */
728: printf(" %s\n", inet_ntop(AF_INET, &pp.addr.addr.v.a.addr.v4.s_addr, buf, 32));
729: #else
730: printf(" rule_flag=%08x action=%d direction=%d log=%d logif=%d "
731: "quick=%d ifnot=%d af=%d type=%d code=%d rdr.port_op=%d rdr.opts=%d\n",
732: pr.rule.rule_flag, pr.rule.action, pr.rule.direction,
733: pr.rule.log, pr.rule.logif, pr.rule.quick, pr.rule.ifnot,
734: pr.rule.af, pr.rule.type, pr.rule.code,
735: pr.rule.rdr.port_op, pr.rule.rdr.opts);
736: printf(" %s\n", inet_ntop(AF_INET, &pr.rule.rdr.addr.v.a.addr.v4.s_addr, buf, 32));
737: #endif
738: }
739: }
740: #endif
741:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>