Annotation of embedaddon/miniupnpd/netfilter/iptcrdr.c, revision 1.1.1.1
1.1 misho 1: /* $Id: iptcrdr.c,v 1.33 2010/09/27 09:17:59 nanard Exp $ */
2: /* MiniUPnP project
3: * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4: * (c) 2006-2008 Thomas Bernard
5: * This software is subject to the conditions detailed
6: * in the LICENCE file provided within the distribution */
7: #include <stdio.h>
8: #include <stdlib.h>
9: #include <string.h>
10: #include <syslog.h>
11: #include <sys/errno.h>
12: #include <sys/socket.h>
13: #include <netinet/in.h>
14: #include <arpa/inet.h>
15: #include <dlfcn.h>
16: #include <libiptc/libiptc.h>
17: #include <iptables.h>
18:
19: #include <linux/version.h>
20:
21: #if IPTABLES_143
22: /* IPTABLES API version >= 1.4.3 */
23: #include <net/netfilter/nf_nat.h>
24: #define ip_nat_multi_range nf_nat_multi_range
25: #define ip_nat_range nf_nat_range
26: #define IPTC_HANDLE struct iptc_handle *
27: #else
28: /* IPTABLES API version < 1.4.3 */
29: #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
30: #include <linux/netfilter_ipv4/ip_nat.h>
31: #else
32: #include <linux/netfilter/nf_nat.h>
33: #endif
34: #define IPTC_HANDLE iptc_handle_t
35: #endif
36:
37: #include "iptcrdr.h"
38: #include "../upnpglobalvars.h"
39:
40: /* dummy init and shutdown functions */
41: int init_redirect(void)
42: {
43: return 0;
44: }
45:
46: void shutdown_redirect(void)
47: {
48: return;
49: }
50:
51: /* convert an ip address to string */
52: static int snprintip(char * dst, size_t size, uint32_t ip)
53: {
54: return snprintf(dst, size,
55: "%u.%u.%u.%u", ip >> 24, (ip >> 16) & 0xff,
56: (ip >> 8) & 0xff, ip & 0xff);
57: }
58:
59: /* netfilter cannot store redirection descriptions, so we use our
60: * own structure to store them */
61: struct rdr_desc {
62: struct rdr_desc * next;
63: unsigned short eport;
64: short proto;
65: char str[];
66: };
67:
68: /* pointer to the chained list where descriptions are stored */
69: static struct rdr_desc * rdr_desc_list = 0;
70:
71: static void
72: add_redirect_desc(unsigned short eport, int proto, const char * desc)
73: {
74: struct rdr_desc * p;
75: size_t l;
76: /* if(desc)
77: {*/
78: if ((l = strlen(desc) + 1) == 1) l = 5;
79: p = malloc(sizeof(struct rdr_desc) + l);
80: if(p)
81: {
82: p->next = rdr_desc_list;
83: p->eport = eport;
84: p->proto = (short)proto;
85: if(desc) memcpy(p->str, desc, l); else memcpy(p->str, "upnp", 4);
86: rdr_desc_list = p;
87: }
88: /* }*/
89: }
90:
91: static void
92: del_redirect_desc(unsigned short eport, int proto)
93: {
94: struct rdr_desc * p, * last;
95: p = rdr_desc_list;
96: last = 0;
97: while(p)
98: {
99: if(p->eport == eport && p->proto == proto)
100: {
101: if(!last)
102: rdr_desc_list = p->next;
103: else
104: last->next = p->next;
105: free(p);
106: return;
107: }
108: last = p;
109: p = p->next;
110: }
111: }
112:
113: static void
114: get_redirect_desc(unsigned short eport, int proto,
115: char * desc, int desclen)
116: {
117: struct rdr_desc * p;
118: if(!desc || (desclen == 0))
119: return;
120: for(p = rdr_desc_list; p; p = p->next)
121: {
122: if(p->eport == eport && p->proto == (short)proto)
123: {
124: strncpy(desc, p->str, desclen);
125: return;
126: }
127: }
128: /* if no description was found, return miniupnpd as default */
129: strncpy(desc, "miniupnpd", desclen);
130: }
131:
132: int
133: get_redirect_desc_by_index(int index, unsigned short * eport, int * proto,
134: char * desc, int desclen)
135: {
136: int i = 0;
137: struct rdr_desc * p;
138: if(!desc || (desclen == 0))
139: return -1;
140: for(p = rdr_desc_list; p; p = p->next, i++)
141: {
142: if(i == index)
143: {
144: *eport = p->eport;
145: *proto = (int)p->proto;
146: strncpy(desc, p->str, desclen);
147: return 0;
148: }
149: }
150: return -1;
151: }
152:
153: /* add_redirect_rule2() */
154: int
155: add_redirect_rule2(const char * ifname, unsigned short eport,
156: const char * iaddr, unsigned short iport, int proto,
157: const char * desc)
158: {
159: int r = addnatrule(proto, eport, iaddr, iport);
160: if(r >= 0)
161: add_redirect_desc(eport, proto, desc);
162: return r;
163: }
164:
165: int
166: add_filter_rule2(const char * ifname, const char * iaddr,
167: unsigned short eport, unsigned short iport,
168: int proto, const char * desc)
169: {
170: return add_filter_rule(proto, iaddr, iport);
171: }
172:
173: /* get_redirect_rule()
174: * returns -1 if the rule is not found */
175: int
176: get_redirect_rule(const char * ifname, unsigned short eport, int proto,
177: char * iaddr, int iaddrlen, unsigned short * iport,
178: char * desc, int desclen,
179: u_int64_t * packets, u_int64_t * bytes)
180: {
181: int r = -1;
182: IPTC_HANDLE h;
183: const struct ipt_entry * e;
184: const struct ipt_entry_target * target;
185: const struct ip_nat_multi_range * mr;
186: const struct ipt_entry_match *match;
187:
188: h = iptc_init("nat");
189: if(!h)
190: {
191: syslog(LOG_ERR, "get_redirect_rule() : "
192: "iptc_init() failed : %s",
193: iptc_strerror(errno));
194: return -1;
195: }
196: if(!iptc_is_chain(miniupnpd_nat_chain, h))
197: {
198: syslog(LOG_ERR, "chain %s not found", miniupnpd_nat_chain);
199: }
200: else
201: {
202: #ifdef IPTABLES_143
203: for(e = iptc_first_rule(miniupnpd_nat_chain, h);
204: e;
205: e = iptc_next_rule(e, h))
206: #else
207: for(e = iptc_first_rule(miniupnpd_nat_chain, &h);
208: e;
209: e = iptc_next_rule(e, &h))
210: #endif
211: {
212: if(proto==e->ip.proto)
213: {
214: match = (const struct ipt_entry_match *)&e->elems;
215: if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN))
216: {
217: const struct ipt_tcp * info;
218: info = (const struct ipt_tcp *)match->data;
219: if(eport != info->dpts[0])
220: continue;
221: }
222: else
223: {
224: const struct ipt_udp * info;
225: info = (const struct ipt_udp *)match->data;
226: if(eport != info->dpts[0])
227: continue;
228: }
229: target = (void *)e + e->target_offset;
230: //target = ipt_get_target(e);
231: mr = (const struct ip_nat_multi_range *)&target->data[0];
232: snprintip(iaddr, iaddrlen, ntohl(mr->range[0].min_ip));
233: *iport = ntohs(mr->range[0].min.all);
234: /*if(desc)
235: strncpy(desc, "miniupnpd", desclen);*/
236: get_redirect_desc(eport, proto, desc, desclen);
237: if(packets)
238: *packets = e->counters.pcnt;
239: if(bytes)
240: *bytes = e->counters.bcnt;
241: r = 0;
242: break;
243: }
244: }
245: }
246: if(h)
247: #ifdef IPTABLES_143
248: iptc_free(h);
249: #else
250: iptc_free(&h);
251: #endif
252: return r;
253: }
254:
255: /* get_redirect_rule_by_index()
256: * return -1 when the rule was not found */
257: int
258: get_redirect_rule_by_index(int index,
259: char * ifname, unsigned short * eport,
260: char * iaddr, int iaddrlen, unsigned short * iport,
261: int * proto, char * desc, int desclen,
262: u_int64_t * packets, u_int64_t * bytes)
263: {
264: int r = -1;
265: r = get_redirect_desc_by_index(index, eport, proto, desc, desclen);
266: if (r==0)
267: r = get_redirect_rule(ifname, *eport, *proto, iaddr, iaddrlen, iport,
268: 0, 0, packets, bytes);
269: #if 0
270: int i = 0;
271: IPTC_HANDLE h;
272: const struct ipt_entry * e;
273: const struct ipt_entry_target * target;
274: const struct ip_nat_multi_range * mr;
275: const struct ipt_entry_match *match;
276:
277: h = iptc_init("nat");
278: if(!h)
279: {
280: syslog(LOG_ERR, "get_redirect_rule_by_index() : "
281: "iptc_init() failed : %s",
282: iptc_strerror(errno));
283: return -1;
284: }
285: if(!iptc_is_chain(miniupnpd_nat_chain, h))
286: {
287: syslog(LOG_ERR, "chain %s not found", miniupnpd_nat_chain);
288: }
289: else
290: {
291: #ifdef IPTABLES_143
292: for(e = iptc_first_rule(miniupnpd_nat_chain, h);
293: e;
294: e = iptc_next_rule(e, h))
295: #else
296: for(e = iptc_first_rule(miniupnpd_nat_chain, &h);
297: e;
298: e = iptc_next_rule(e, &h))
299: #endif
300: {
301: if(i==index)
302: {
303: *proto = e->ip.proto;
304: match = (const struct ipt_entry_match *)&e->elems;
305: if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN))
306: {
307: const struct ipt_tcp * info;
308: info = (const struct ipt_tcp *)match->data;
309: *eport = info->dpts[0];
310: }
311: else
312: {
313: const struct ipt_udp * info;
314: info = (const struct ipt_udp *)match->data;
315: *eport = info->dpts[0];
316: }
317: target = (void *)e + e->target_offset;
318: mr = (const struct ip_nat_multi_range *)&target->data[0];
319: snprintip(iaddr, iaddrlen, ntohl(mr->range[0].min_ip));
320: *iport = ntohs(mr->range[0].min.all);
321: /*if(desc)
322: strncpy(desc, "miniupnpd", desclen);*/
323: get_redirect_desc(*eport, *proto, desc, desclen);
324: if(packets)
325: *packets = e->counters.pcnt;
326: if(bytes)
327: *bytes = e->counters.bcnt;
328: r = 0;
329: break;
330: }
331: i++;
332: }
333: }
334: if(h)
335: #ifdef IPTABLES_143
336: iptc_free(h);
337: #else
338: iptc_free(&h);
339: #endif
340: #endif /*0*/
341: return r;
342: }
343:
344: /* delete_rule_and_commit() :
345: * subfunction used in delete_redirect_and_filter_rules() */
346: int
347: delete_rule_and_commit(const char * table,
348: const char * miniupnpd_chain,
349: unsigned short eport, int proto,
350: const char * logcaller)
351: {
352: int r = -1;
353: unsigned index = 0;
354: unsigned i = 0;
355: IPTC_HANDLE h;
356: const struct ipt_entry * e;
357: const struct ipt_entry_match *match;
358:
359: h = iptc_init(table);
360: if(!h)
361: {
362: syslog(LOG_ERR, "get_index_rules() : "
363: "iptc_init(%s) failed : %s",
364: table,
365: iptc_strerror(errno));
366: return -1;
367: }
368: if(!iptc_is_chain(miniupnpd_chain, h))
369: {
370: syslog(LOG_ERR, "chain %s not found", miniupnpd_chain);
371: }
372: else
373: {
374: #ifdef IPTABLES_143
375: for(e = iptc_first_rule(miniupnpd_chain, h);
376: e;
377: e = iptc_next_rule(e, h), i++)
378: #else
379: for(e = iptc_first_rule(miniupnpd_chain, &h);
380: e;
381: e = iptc_next_rule(e, &h), i++)
382: #endif
383: {
384: if(proto==e->ip.proto)
385: {
386: match = (const struct ipt_entry_match *)&e->elems;
387: if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN))
388: {
389: const struct ipt_tcp * info;
390: info = (const struct ipt_tcp *)match->data;
391: if(eport != info->dpts[0])
392: continue;
393: }
394: else
395: {
396: const struct ipt_udp * info;
397: info = (const struct ipt_udp *)match->data;
398: if(eport != info->dpts[0])
399: continue;
400: }
401: r = 0;
402: index = i;
403: break;
404: }
405: }
406: }
407: if(h)
408: #ifdef IPTABLES_143
409: iptc_free(h);
410: #else
411: iptc_free(&h);
412: #endif
413: if ((r == 0) && (h = iptc_init(table))) {
414: syslog(LOG_INFO, "Trying to delete rules at index %u", index);
415: /* Now delete both rules */
416: #ifdef IPTABLES_143
417: if(!iptc_delete_num_entry(miniupnpd_chain, index, h))
418: #else
419: if(!iptc_delete_num_entry(miniupnpd_chain, index, &h))
420: #endif
421: {
422: syslog(LOG_ERR, "%s() : iptc_delete_num_entry(): %s\n",
423: logcaller, iptc_strerror(errno));
424: r = -1;
425: }
426: #ifdef IPTABLES_143
427: else if(!iptc_commit(h))
428: #else
429: else if(!iptc_commit(&h))
430: #endif
431: {
432: syslog(LOG_ERR, "%s() : iptc_commit(): %s\n",
433: logcaller, iptc_strerror(errno));
434: r = -1;
435: }
436: if(h)
437: #ifdef IPTABLES_143
438: iptc_free(h);
439: #else
440: iptc_free(&h);
441: #endif
442: }
443: return r;
444: }
445:
446: /* delete_redirect_and_filter_rules()
447: */
448: int
449: delete_redirect_and_filter_rules(unsigned short eport, int proto)
450: {
451: int r = -1;
452: if ((r = delete_rule_and_commit("nat", miniupnpd_nat_chain, eport, proto, "delete_redirect_rule") &&
453: delete_rule_and_commit("filter", miniupnpd_forward_chain, eport, proto, "delete_filter_rule")) == 0)
454: del_redirect_desc(eport, proto);
455: return r;
456: }
457:
458: /* ==================================== */
459: /* TODO : add the -m state --state NEW,ESTABLISHED,RELATED
460: * only for the filter rule */
461: static struct ipt_entry_match *
462: get_tcp_match(unsigned short dport)
463: {
464: struct ipt_entry_match *match;
465: struct ipt_tcp * tcpinfo;
466: size_t size;
467: size = IPT_ALIGN(sizeof(struct ipt_entry_match))
468: + IPT_ALIGN(sizeof(struct ipt_tcp));
469: match = calloc(1, size);
470: match->u.match_size = size;
471: strncpy(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN);
472: tcpinfo = (struct ipt_tcp *)match->data;
473: tcpinfo->spts[0] = 0; /* all source ports */
474: tcpinfo->spts[1] = 0xFFFF;
475: tcpinfo->dpts[0] = dport; /* specified destination port */
476: tcpinfo->dpts[1] = dport;
477: return match;
478: }
479:
480: static struct ipt_entry_match *
481: get_udp_match(unsigned short dport)
482: {
483: struct ipt_entry_match *match;
484: struct ipt_udp * udpinfo;
485: size_t size;
486: size = IPT_ALIGN(sizeof(struct ipt_entry_match))
487: + IPT_ALIGN(sizeof(struct ipt_udp));
488: match = calloc(1, size);
489: match->u.match_size = size;
490: strncpy(match->u.user.name, "udp", IPT_FUNCTION_MAXNAMELEN);
491: udpinfo = (struct ipt_udp *)match->data;
492: udpinfo->spts[0] = 0; /* all source ports */
493: udpinfo->spts[1] = 0xFFFF;
494: udpinfo->dpts[0] = dport; /* specified destination port */
495: udpinfo->dpts[1] = dport;
496: return match;
497: }
498:
499: static struct ipt_entry_target *
500: get_dnat_target(const char * daddr, unsigned short dport)
501: {
502: struct ipt_entry_target * target;
503: struct ip_nat_multi_range * mr;
504: struct ip_nat_range * range;
505: size_t size;
506:
507: size = IPT_ALIGN(sizeof(struct ipt_entry_target))
508: + IPT_ALIGN(sizeof(struct ip_nat_multi_range));
509: target = calloc(1, size);
510: target->u.target_size = size;
511: strncpy(target->u.user.name, "DNAT", IPT_FUNCTION_MAXNAMELEN);
512: /* one ip_nat_range already included in ip_nat_multi_range */
513: mr = (struct ip_nat_multi_range *)&target->data[0];
514: mr->rangesize = 1;
515: range = &mr->range[0];
516: range->min_ip = range->max_ip = inet_addr(daddr);
517: range->flags |= IP_NAT_RANGE_MAP_IPS;
518: range->min.all = range->max.all = htons(dport);
519: range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
520: return target;
521: }
522:
523: /* iptc_init_verify_and_append()
524: * return 0 on success, -1 on failure */
525: static int
526: iptc_init_verify_and_append(const char * table, const char * miniupnpd_chain, struct ipt_entry * e,
527: const char * logcaller)
528: {
529: IPTC_HANDLE h;
530: h = iptc_init(table);
531: if(!h)
532: {
533: syslog(LOG_ERR, "%s : iptc_init() error : %s\n",
534: logcaller, iptc_strerror(errno));
535: return -1;
536: }
537: if(!iptc_is_chain(miniupnpd_chain, h))
538: {
539: syslog(LOG_ERR, "%s : iptc_is_chain() error : %s\n",
540: logcaller, iptc_strerror(errno));
541: if(h)
542: #ifdef IPTABLES_143
543: iptc_free(h);
544: #else
545: iptc_free(&h);
546: #endif
547: return -1;
548: }
549: /* iptc_insert_entry(miniupnpd_chain, e, n, h/&h) could also be used */
550: #ifdef IPTABLES_143
551: if(!iptc_append_entry(miniupnpd_chain, e, h))
552: #else
553: if(!iptc_append_entry(miniupnpd_chain, e, &h))
554: #endif
555: {
556: syslog(LOG_ERR, "%s : iptc_append_entry() error : %s\n",
557: logcaller, iptc_strerror(errno));
558: if(h)
559: #ifdef IPTABLES_143
560: iptc_free(h);
561: #else
562: iptc_free(&h);
563: #endif
564: return -1;
565: }
566: #ifdef IPTABLES_143
567: if(!iptc_commit(h))
568: #else
569: if(!iptc_commit(&h))
570: #endif
571: {
572: syslog(LOG_ERR, "%s : iptc_commit() error : %s\n",
573: logcaller, iptc_strerror(errno));
574: if(h)
575: #ifdef IPTABLES_143
576: iptc_free(h);
577: #else
578: iptc_free(&h);
579: #endif
580: return -1;
581: }
582: if(h)
583: #ifdef IPTABLES_143
584: iptc_free(h);
585: #else
586: iptc_free(&h);
587: #endif
588: return 0;
589: }
590:
591: /* add nat rule
592: * iptables -t nat -A MINIUPNPD -p proto --dport eport -j DNAT --to iaddr:iport
593: * */
594: int
595: addnatrule(int proto, unsigned short eport,
596: const char * iaddr, unsigned short iport)
597: {
598: int r = 0;
599: struct ipt_entry * e;
600: struct ipt_entry_match *match = NULL;
601: struct ipt_entry_target *target = NULL;
602:
603: e = calloc(1, sizeof(struct ipt_entry));
604: e->ip.proto = proto;
605: if(proto == IPPROTO_TCP)
606: {
607: match = get_tcp_match(eport);
608: }
609: else
610: {
611: match = get_udp_match(eport);
612: }
613: e->nfcache = NFC_IP_DST_PT;
614: target = get_dnat_target(iaddr, iport);
615: e->nfcache |= NFC_UNKNOWN;
616: e = realloc(e, sizeof(struct ipt_entry)
617: + match->u.match_size
618: + target->u.target_size);
619: memcpy(e->elems, match, match->u.match_size);
620: memcpy(e->elems + match->u.match_size, target, target->u.target_size);
621: e->target_offset = sizeof(struct ipt_entry)
622: + match->u.match_size;
623: e->next_offset = sizeof(struct ipt_entry)
624: + match->u.match_size
625: + target->u.target_size;
626:
627: r = iptc_init_verify_and_append("nat", miniupnpd_nat_chain, e, "addnatrule()");
628: free(target);
629: free(match);
630: free(e);
631: return r;
632: }
633: /* ================================= */
634: static struct ipt_entry_target *
635: get_accept_target(void)
636: {
637: struct ipt_entry_target * target = NULL;
638: size_t size;
639: size = IPT_ALIGN(sizeof(struct ipt_entry_target))
640: + IPT_ALIGN(sizeof(int));
641: target = calloc(1, size);
642: target->u.user.target_size = size;
643: strncpy(target->u.user.name, "ACCEPT", IPT_FUNCTION_MAXNAMELEN);
644: return target;
645: }
646:
647: /* add_filter_rule()
648: * */
649: int
650: add_filter_rule(int proto, const char * iaddr, unsigned short iport)
651: {
652: int r = 0;
653: struct ipt_entry * e;
654: struct ipt_entry_match *match = NULL;
655: struct ipt_entry_target *target = NULL;
656:
657: e = calloc(1, sizeof(struct ipt_entry));
658: e->ip.proto = proto;
659: if(proto == IPPROTO_TCP)
660: {
661: match = get_tcp_match(iport);
662: }
663: else
664: {
665: match = get_udp_match(iport);
666: }
667: e->nfcache = NFC_IP_DST_PT;
668: e->ip.dst.s_addr = inet_addr(iaddr);
669: e->ip.dmsk.s_addr = INADDR_NONE;
670: target = get_accept_target();
671: e->nfcache |= NFC_UNKNOWN;
672: e = realloc(e, sizeof(struct ipt_entry)
673: + match->u.match_size
674: + target->u.target_size);
675: memcpy(e->elems, match, match->u.match_size);
676: memcpy(e->elems + match->u.match_size, target, target->u.target_size);
677: e->target_offset = sizeof(struct ipt_entry)
678: + match->u.match_size;
679: e->next_offset = sizeof(struct ipt_entry)
680: + match->u.match_size
681: + target->u.target_size;
682:
683: r = iptc_init_verify_and_append("filter", miniupnpd_forward_chain, e, "add_filter_rule()");
684: free(target);
685: free(match);
686: free(e);
687: return r;
688: }
689:
690: /* ================================ */
691: static int
692: print_match(const struct ipt_entry_match *match)
693: {
694: printf("match %s\n", match->u.user.name);
695: if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN))
696: {
697: struct ipt_tcp * tcpinfo;
698: tcpinfo = (struct ipt_tcp *)match->data;
699: printf("srcport = %hu:%hu dstport = %hu:%hu\n",
700: tcpinfo->spts[0], tcpinfo->spts[1],
701: tcpinfo->dpts[0], tcpinfo->dpts[1]);
702: }
703: else if(0 == strncmp(match->u.user.name, "udp", IPT_FUNCTION_MAXNAMELEN))
704: {
705: struct ipt_udp * udpinfo;
706: udpinfo = (struct ipt_udp *)match->data;
707: printf("srcport = %hu:%hu dstport = %hu:%hu\n",
708: udpinfo->spts[0], udpinfo->spts[1],
709: udpinfo->dpts[0], udpinfo->dpts[1]);
710: }
711: return 0;
712: }
713:
714: static void
715: print_iface(const char * iface, const unsigned char * mask, int invert)
716: {
717: unsigned i;
718: if(mask[0] == 0)
719: return;
720: if(invert)
721: printf("! ");
722: for(i=0; i<IFNAMSIZ; i++)
723: {
724: if(mask[i])
725: {
726: if(iface[i])
727: putchar(iface[i]);
728: }
729: else
730: {
731: if(iface[i-1])
732: putchar('+');
733: break;
734: }
735: }
736: }
737:
738: static void
739: printip(uint32_t ip)
740: {
741: printf("%u.%u.%u.%u", ip >> 24, (ip >> 16) & 0xff,
742: (ip >> 8) & 0xff, ip & 0xff);
743: }
744:
745: /* for debug */
746: /* read the "filter" and "nat" tables */
747: int
748: list_redirect_rule(const char * ifname)
749: {
750: IPTC_HANDLE h;
751: const struct ipt_entry * e;
752: const struct ipt_entry_target * target;
753: const struct ip_nat_multi_range * mr;
754: const char * target_str;
755:
756: h = iptc_init("nat");
757: if(!h)
758: {
759: printf("iptc_init() error : %s\n", iptc_strerror(errno));
760: return -1;
761: }
762: if(!iptc_is_chain(miniupnpd_nat_chain, h))
763: {
764: printf("chain %s not found\n", miniupnpd_nat_chain);
765: #ifdef IPTABLES_143
766: iptc_free(h);
767: #else
768: iptc_free(&h);
769: #endif
770: return -1;
771: }
772: #ifdef IPTABLES_143
773: for(e = iptc_first_rule(miniupnpd_nat_chain, h);
774: e;
775: e = iptc_next_rule(e, h))
776: {
777: target_str = iptc_get_target(e, h);
778: #else
779: for(e = iptc_first_rule(miniupnpd_nat_chain, &h);
780: e;
781: e = iptc_next_rule(e, &h))
782: {
783: target_str = iptc_get_target(e, &h);
784: #endif
785: printf("===\n");
786: printf("src = %s%s/%s\n", (e->ip.invflags & IPT_INV_SRCIP)?"! ":"",
787: inet_ntoa(e->ip.src), inet_ntoa(e->ip.smsk));
788: printf("dst = %s%s/%s\n", (e->ip.invflags & IPT_INV_DSTIP)?"! ":"",
789: inet_ntoa(e->ip.dst), inet_ntoa(e->ip.dmsk));
790: /*printf("in_if = %s out_if = %s\n", e->ip.iniface, e->ip.outiface);*/
791: printf("in_if = ");
792: print_iface(e->ip.iniface, e->ip.iniface_mask,
793: e->ip.invflags & IPT_INV_VIA_IN);
794: printf(" out_if = ");
795: print_iface(e->ip.outiface, e->ip.outiface_mask,
796: e->ip.invflags & IPT_INV_VIA_OUT);
797: printf("\n");
798: printf("ip.proto = %s%d\n", (e->ip.invflags & IPT_INV_PROTO)?"! ":"",
799: e->ip.proto);
800: /* display matches stuff */
801: if(e->target_offset)
802: {
803: IPT_MATCH_ITERATE(e, print_match);
804: /*printf("\n");*/
805: }
806: printf("target = %s\n", target_str);
807: target = (void *)e + e->target_offset;
808: mr = (const struct ip_nat_multi_range *)&target->data[0];
809: printf("ips ");
810: printip(ntohl(mr->range[0].min_ip));
811: printf(" ");
812: printip(ntohl(mr->range[0].max_ip));
813: printf("\nports %hu %hu\n", ntohs(mr->range[0].min.all),
814: ntohs(mr->range[0].max.all));
815: printf("flags = %x\n", mr->range[0].flags);
816: }
817: if(h)
818: #ifdef IPTABLES_143
819: iptc_free(h);
820: #else
821: iptc_free(&h);
822: #endif
823: return 0;
824: }
825:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>