Annotation of embedaddon/miniupnpd/ipf/ipfrdr.c, revision 1.1.1.2
1.1.1.2 ! misho 1: /* $Id: ipfrdr.c,v 1.13 2012/03/19 21:14:13 nanard Exp $ */
1.1 misho 2: /* MiniUPnP project
3: * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4: * (c) 2007 Darren Reed
5: * This software is subject to the conditions detailed
6: * in the LICENCE file provided within the distribution */
7:
8: #include <sys/param.h>
9: #include <sys/types.h>
10: #include <sys/file.h>
11: /*
12: * This is a workaround for <sys/uio.h> troubles on FreeBSD, HPUX, OpenBSD.
13: * Needed here because on some systems <sys/uio.h> gets included by things
14: * like <sys/socket.h>
15: */
16: #ifndef _KERNEL
17: # define ADD_KERNEL
18: # define _KERNEL
19: # define KERNEL
20: #endif
21: #ifdef __OpenBSD__
22: struct file;
23: #endif
24: #include <sys/uio.h>
25: #ifdef ADD_KERNEL
26: # undef _KERNEL
27: # undef KERNEL
28: #endif
29: #include <sys/time.h>
30: #include <sys/socket.h>
31: #include <sys/syslog.h>
32: #include <sys/ioctl.h>
33: #include <net/if.h>
34: #if __FreeBSD_version >= 300000
35: # include <net/if_var.h>
36: #endif
37: #include <netinet/in.h>
38: #include <netinet/in_systm.h>
39: #include <netinet/ip.h>
40: #include <netinet/ip_icmp.h>
41: #ifndef TCP_PAWS_IDLE /* IRIX */
42: # include <netinet/tcp.h>
43: #endif
44: #include <netinet/udp.h>
45:
46: #include <arpa/inet.h>
47:
48: #include <errno.h>
49: #include <limits.h>
50: #include <netdb.h>
51: #include <stdlib.h>
52: #include <fcntl.h>
53: #include <syslog.h>
54: #include <stddef.h>
55: #include <stdio.h>
56: #if !defined(__SVR4) && !defined(__svr4__) && defined(sun)
57: # include <strings.h>
58: #endif
59: #include <string.h>
60: #include <unistd.h>
61:
62: #include "../config.h"
63: #include "netinet/ipl.h"
64: #include "netinet/ip_compat.h"
65: #include "netinet/ip_fil.h"
66: #include "netinet/ip_nat.h"
67: #include "netinet/ip_state.h"
68:
69:
70: #ifndef __P
71: # ifdef __STDC__
72: # define __P(x) x
73: # else
74: # define __P(x) ()
75: # endif
76: #endif
77: #ifndef __STDC__
78: # undef const
79: # define const
80: #endif
81:
82: #ifndef U_32_T
83: # define U_32_T 1
84: # if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || \
85: defined(__sgi)
86: typedef u_int32_t u_32_t;
87: # else
88: # if defined(__alpha__) || defined(__alpha) || defined(_LP64)
89: typedef unsigned int u_32_t;
90: # else
91: # if SOLARIS2 >= 6
92: typedef uint32_t u_32_t;
93: # else
94: typedef unsigned int u_32_t;
95: # endif
96: # endif
97: # endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ || __sgi */
98: #endif /* U_32_T */
99:
100:
101: #if defined(__NetBSD__) || defined(__OpenBSD__) || \
102: (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) || \
103: SOLARIS || defined(__sgi) || defined(__osf__) || defined(linux)
104: # include <stdarg.h>
105: typedef int (* ioctlfunc_t) __P((int, ioctlcmd_t, ...));
106: #else
107: typedef int (* ioctlfunc_t) __P((dev_t, ioctlcmd_t, void *));
108: #endif
109: typedef void (* addfunc_t) __P((int, ioctlfunc_t, void *));
110: typedef int (* copyfunc_t) __P((void *, void *, size_t));
111:
112:
113: /*
114: * SunOS4
115: */
116: #if defined(sun) && !defined(__SVR4) && !defined(__svr4__)
117: extern int ioctl __P((int, int, void *));
118: #endif
119:
120: #include "../upnpglobalvars.h"
121:
122: /* group name */
123: static const char group_name[] = "miniupnpd";
124:
125: static int dev = -1;
126: static int dev_ipl = -1;
127:
128: /* IPFilter cannot store redirection descriptions, so we use our
129: * own structure to store them */
130: struct rdr_desc {
131: struct rdr_desc * next;
132: unsigned short eport;
133: int proto;
1.1.1.2 ! misho 134: unsigned int timestamp;
1.1 misho 135: char str[];
136: };
137:
138: /* pointer to the chained list where descriptions are stored */
139: static struct rdr_desc * rdr_desc_list;
140:
141: static void
1.1.1.2 ! misho 142: add_redirect_desc(unsigned short eport, int proto,
! 143: unsigned int timestamp, const char * desc)
1.1 misho 144: {
145: struct rdr_desc * p;
146: size_t l;
1.1.1.2 ! misho 147:
1.1 misho 148: if (desc != NULL) {
149: l = strlen(desc) + 1;
150: p = malloc(sizeof(struct rdr_desc) + l);
151: if (p) {
152: p->next = rdr_desc_list;
153: p->eport = eport;
154: p->proto = proto;
1.1.1.2 ! misho 155: p->timestamp = timestamp;
1.1 misho 156: memcpy(p->str, desc, l);
157: rdr_desc_list = p;
158: }
159: }
160: }
161:
162: static void
163: del_redirect_desc(unsigned short eport, int proto)
164: {
165: struct rdr_desc * p, * last;
166:
167: last = NULL;
168: for (p = rdr_desc_list; p; p = p->next) {
169: if(p->eport == eport && p->proto == proto) {
170: if (last == NULL)
171: rdr_desc_list = p->next;
172: else
173: last->next = p->next;
174: free(p);
175: return;
176: }
177: }
178: }
179:
180: static void
1.1.1.2 ! misho 181: get_redirect_desc(unsigned short eport, int proto, char * desc, int desclen, unsigned int * timestamp)
1.1 misho 182: {
183: struct rdr_desc * p;
1.1.1.2 ! misho 184:
1.1 misho 185: if (desc == NULL || desclen == 0)
186: return;
187: for (p = rdr_desc_list; p; p = p->next) {
188: if (p->eport == eport && p->proto == proto)
189: {
190: strncpy(desc, p->str, desclen);
1.1.1.2 ! misho 191: *timestamp = p->timestamp;
1.1 misho 192: return;
193: }
194: }
1.1.1.2 ! misho 195: return;
1.1 misho 196: }
197:
198: int init_redirect(void)
199: {
1.1.1.2 ! misho 200:
1.1 misho 201: dev = open(IPNAT_NAME, O_RDWR);
202: if (dev < 0) {
203: syslog(LOG_ERR, "open(\"%s\"): %m", IPNAT_NAME);
204: return -1;
205: }
206: dev_ipl = open(IPL_NAME, O_RDWR);
207: if (dev_ipl < 0) {
208: syslog(LOG_ERR, "open(\"%s\"): %m", IPL_NAME);
209: return -1;
210: }
211: return 0;
212: }
213:
214: void shutdown_redirect(void)
215: {
1.1.1.2 ! misho 216:
1.1 misho 217: if (dev >= 0) {
218: close(dev);
219: dev = -1;
220: }
221: if (dev_ipl >= 0) {
222: close(dev_ipl);
223: dev = -1;
224: }
225: return;
226: }
227:
228: int
1.1.1.2 ! misho 229: add_redirect_rule2(const char * ifname, const char * rhost,
! 230: unsigned short eport, const char * iaddr, unsigned short iport,
! 231: int proto, const char * desc, unsigned int timestamp)
1.1 misho 232: {
233: struct ipnat ipnat;
234: struct ipfobj obj;
235: int r;
236:
237: if (dev < 0) {
238: syslog(LOG_ERR, "%s not open", IPNAT_NAME);
239: return -1;
240: }
241:
242: memset(&obj, 0, sizeof(obj));
243: memset(&ipnat, 0, sizeof(ipnat));
244:
245: ipnat.in_redir = NAT_REDIRECT;
246: ipnat.in_p = proto;
247: if (proto == IPPROTO_TCP)
248: ipnat.in_flags = IPN_TCP;
249: if (proto == IPPROTO_UDP)
250: ipnat.in_flags = IPN_UDP;
251: ipnat.in_dcmp = FR_EQUAL;
252: ipnat.in_pmin = htons(eport);
253: ipnat.in_pmax = htons(eport);
254: ipnat.in_pnext = htons(iport);
255: ipnat.in_v = 4;
256: strlcpy(ipnat.in_tag.ipt_tag, group_name, IPFTAG_LEN);
257:
258: #ifdef USE_IFNAME_IN_RULES
259: if (ifname) {
260: strlcpy(ipnat.in_ifnames[0], ifname, IFNAMSIZ);
261: strlcpy(ipnat.in_ifnames[1], ifname, IFNAMSIZ);
262: }
263: #endif
264:
1.1.1.2 ! misho 265: if(rhost && rhost[0] != '\0' && rhost[0] != '*')
! 266: {
! 267: inet_pton(AF_INET, rhost, &ipnat.in_src[0].in4);
! 268: ipnat.in_src[1].in4.s_addr = 0xffffffff;
! 269: }
! 270:
1.1 misho 271: inet_pton(AF_INET, iaddr, &ipnat.in_in[0].in4);
272: ipnat.in_in[1].in4.s_addr = 0xffffffff;
273:
274: obj.ipfo_rev = IPFILTER_VERSION;
275: obj.ipfo_size = sizeof(ipnat);
276: obj.ipfo_ptr = &ipnat;
277: obj.ipfo_type = IPFOBJ_IPNAT;
278:
279: r = ioctl(dev, SIOCADNAT, &obj);
280: if (r == -1)
281: syslog(LOG_ERR, "ioctl(SIOCADNAT): %m");
282: else
1.1.1.2 ! misho 283: add_redirect_desc(eport, proto, timestamp, desc);
1.1 misho 284: return r;
285: }
286:
287: /* get_redirect_rule()
288: * return value : 0 success (found)
289: * -1 = error or rule not found */
290: int
291: get_redirect_rule(const char * ifname, unsigned short eport, int proto,
292: char * iaddr, int iaddrlen, unsigned short * iport,
293: char * desc, int desclen,
1.1.1.2 ! misho 294: char * rhost, int rhostlen,
! 295: unsigned int * timestamp,
1.1 misho 296: u_int64_t * packets, u_int64_t * bytes)
297: {
298: ipfgeniter_t iter;
299: ipfobj_t obj;
300: ipnat_t ipn;
301: int r;
302:
303: memset(&obj, 0, sizeof(obj));
304: obj.ipfo_rev = IPFILTER_VERSION;
305: obj.ipfo_type = IPFOBJ_GENITER;
306: obj.ipfo_size = sizeof(iter);
307: obj.ipfo_ptr = &iter;
308:
309: iter.igi_type = IPFGENITER_IPNAT;
310: #if IPFILTER_VERSION > 4011300
311: iter.igi_nitems = 1;
312: #endif
313: iter.igi_data = &ipn;
314:
315: if (dev < 0) {
316: syslog(LOG_ERR, "%s not open", IPNAT_NAME);
317: return -1;
318: }
319:
320: r = -1;
321: do {
322: if (ioctl(dev, SIOCGENITER, &obj) == -1) {
323: syslog(LOG_ERR, "ioctl(dev, SIOCGENITER): %m");
324: break;
325: }
326: if (eport == ntohs(ipn.in_pmin) &&
327: eport == ntohs(ipn.in_pmax) &&
328: strcmp(ipn.in_tag.ipt_tag, group_name) == 0 &&
329: ipn.in_p == proto)
330: {
331: strlcpy(desc, "", desclen);
332: if (packets != NULL)
333: *packets = 0;
334: if (bytes != NULL)
335: *bytes = 0;
336: if (iport != NULL)
337: *iport = ntohs(ipn.in_pnext);
1.1.1.2 ! misho 338: if ((desc != NULL) && (timestamp != NULL))
! 339: get_redirect_desc(eport, proto, desc, desclen, timestamp);
! 340: if ((rhost != NULL) && (rhostlen > 0))
! 341: inet_ntop(AF_INET, &ipn.in_src[0].in4, rhost, rhostlen);
1.1 misho 342: inet_ntop(AF_INET, &ipn.in_in[0].in4, iaddr, iaddrlen);
343: r = 0;
344: }
345: } while (ipn.in_next != NULL);
346: return r;
347: }
348:
349:
350: int
351: get_redirect_rule_by_index(int index,
352: char * ifname, unsigned short * eport,
353: char * iaddr, int iaddrlen, unsigned short * iport,
354: int * proto, char * desc, int desclen,
1.1.1.2 ! misho 355: char * rhost, int rhostlen,
! 356: unsigned int * timestamp,
1.1 misho 357: u_int64_t * packets, u_int64_t * bytes)
358: {
359: ipfgeniter_t iter;
360: ipfobj_t obj;
361: ipnat_t ipn;
362: int n, r;
363:
364: if (index < 0)
365: return -1;
366:
367: if (dev < 0) {
368: syslog(LOG_ERR, "%s not open", IPNAT_NAME);
369: return -1;
370: }
371:
372: memset(&obj, 0, sizeof(obj));
373: obj.ipfo_rev = IPFILTER_VERSION;
374: obj.ipfo_ptr = &iter;
375: obj.ipfo_size = sizeof(iter);
376: obj.ipfo_type = IPFOBJ_GENITER;
377:
378: iter.igi_type = IPFGENITER_IPNAT;
379: #if IPFILTER_VERSION > 4011300
380: iter.igi_nitems = 1;
381: #endif
382: iter.igi_data = &ipn;
383:
384: n = 0;
385: r = -1;
386: do {
387: if (ioctl(dev, SIOCGENITER, &obj) == -1) {
388: syslog(LOG_ERR, "%s:ioctl(SIOCGENITER): %m",
389: "get_redirect_rule_by_index");
390: break;
391: }
392:
393: if (strcmp(ipn.in_tag.ipt_tag, group_name) != 0)
394: continue;
395:
396: if (index == n++) {
397: *proto = ipn.in_p;
398: *eport = ntohs(ipn.in_pmax);
399: *iport = ntohs(ipn.in_pnext);
400:
401: if (ifname)
402: strlcpy(ifname, ipn.in_ifnames[0], IFNAMSIZ);
403: if (packets != NULL)
404: *packets = 0;
405: if (bytes != NULL)
406: *bytes = 0;
1.1.1.2 ! misho 407: if ((desc != NULL) && (timestamp != NULL))
! 408: get_redirect_desc(*eport, *proto, desc, desclen, timestamp);
! 409: if ((rhost != NULL) && (rhostlen > 0))
! 410: inet_ntop(AF_INET, &ipn.in_src[0].in4, rhost, rhostlen);
1.1 misho 411: inet_ntop(AF_INET, &ipn.in_in[0].in4, iaddr, iaddrlen);
412: r = 0;
413: }
414: } while (ipn.in_next != NULL);
415: return r;
416: }
417:
418: static int
419: real_delete_redirect_rule(const char * ifname, unsigned short eport, int proto)
420: {
421: ipfgeniter_t iter;
422: ipfobj_t obj;
423: ipnat_t ipn;
424: int r;
425:
426: memset(&obj, 0, sizeof(obj));
427: obj.ipfo_rev = IPFILTER_VERSION;
428: obj.ipfo_type = IPFOBJ_GENITER;
429: obj.ipfo_size = sizeof(iter);
430: obj.ipfo_ptr = &iter;
431:
432: iter.igi_type = IPFGENITER_IPNAT;
433: #if IPFILTER_VERSION > 4011300
434: iter.igi_nitems = 1;
435: #endif
436: iter.igi_data = &ipn;
437:
438: if (dev < 0) {
439: syslog(LOG_ERR, "%s not open", IPNAT_NAME);
440: return -1;
441: }
442:
443: r = -1;
444: do {
445: if (ioctl(dev, SIOCGENITER, &obj) == -1) {
446: syslog(LOG_ERR, "%s:ioctl(SIOCGENITER): %m",
447: "delete_redirect_rule");
448: break;
449: }
450: if (eport == ntohs(ipn.in_pmin) &&
451: eport == ntohs(ipn.in_pmax) &&
452: strcmp(ipn.in_tag.ipt_tag, group_name) == 0 &&
453: ipn.in_p == proto)
454: {
455: obj.ipfo_rev = IPFILTER_VERSION;
456: obj.ipfo_size = sizeof(ipn);
457: obj.ipfo_ptr = &ipn;
458: obj.ipfo_type = IPFOBJ_IPNAT;
459: r = ioctl(dev, SIOCRMNAT, &obj);
460: if (r == -1)
461: syslog(LOG_ERR, "%s:ioctl(SIOCRMNAT): %m",
462: "delete_redirect_rule");
463: /* Delete the desc even if the above failed */
464: del_redirect_desc(eport, proto);
465: break;
466: }
467: } while (ipn.in_next != NULL);
468: return r;
469: }
470:
471: /* FIXME: For some reason, the iter isn't reset every other delete,
472: * so we attempt 2 deletes. */
473: int
474: delete_redirect_rule(const char * ifname, unsigned short eport, int proto)
475: {
476: int r;
477:
478: r = real_delete_redirect_rule(ifname, eport, proto);
479: if (r == -1)
480: r = real_delete_redirect_rule(ifname, eport, proto);
481: return r;
482: }
483:
484: /* thanks to Seth Mos for this function */
485: int
1.1.1.2 ! misho 486: add_filter_rule2(const char * ifname, const char * rhost,
! 487: const char * iaddr, unsigned short eport, unsigned short iport,
1.1 misho 488: int proto, const char * desc)
489: {
490: ipfobj_t obj;
491: frentry_t fr;
492: fripf_t ipffr;
493: int r;
494:
495: if (dev_ipl < 0) {
496: syslog(LOG_ERR, "%s not open", IPL_NAME);
497: return -1;
498: }
499:
500: memset(&obj, 0, sizeof(obj));
501: memset(&fr, 0, sizeof(fr));
502: memset(&ipffr, 0, sizeof(ipffr));
503:
504: fr.fr_flags = FR_PASS|FR_KEEPSTATE|FR_QUICK|FR_INQUE;
505: if (GETFLAG(LOGPACKETSMASK))
506: fr.fr_flags |= FR_LOG|FR_LOGFIRST;
507: fr.fr_v = 4;
508:
509: fr.fr_type = FR_T_IPF;
510: fr.fr_dun.fru_ipf = &ipffr;
511: fr.fr_dsize = sizeof(ipffr);
512: fr.fr_isc = (void *)-1;
513:
514: fr.fr_proto = proto;
515: fr.fr_mproto = 0xff;
516: fr.fr_dcmp = FR_EQUAL;
517: fr.fr_dport = eport;
518: #ifdef USE_IFNAME_IN_RULES
519: if (ifname)
520: strlcpy(fr.fr_ifnames[0], ifname, IFNAMSIZ);
521: #endif
522: strlcpy(fr.fr_group, group_name, sizeof(fr.fr_group));
523:
524: if (proto == IPPROTO_TCP) {
525: fr.fr_tcpf = TH_SYN;
526: fr.fr_tcpfm = TH_SYN|TH_ACK|TH_RST|TH_FIN|TH_URG|TH_PUSH;
527: }
528:
1.1.1.2 ! misho 529: if(rhost && rhost[0] != '\0' && rhost[0] != '*')
! 530: {
! 531: inet_pton(AF_INET, rhost, &fr.fr_saddr);
! 532: fr.fr_smask = 0xffffffff;
! 533: }
! 534:
1.1 misho 535: inet_pton(AF_INET, iaddr, &fr.fr_daddr);
536: fr.fr_dmask = 0xffffffff;
537:
538: obj.ipfo_rev = IPFILTER_VERSION;
539: obj.ipfo_ptr = &fr;
540: obj.ipfo_size = sizeof(fr);
541:
542: r = ioctl(dev_ipl, SIOCINAFR, &obj);
543: if (r == -1) {
544: if (errno == ESRCH)
545: syslog(LOG_ERR,
546: "SIOCINAFR(missing 'head %s' rule?):%m",
547: group_name);
548: else
549: syslog(LOG_ERR, "SIOCINAFR:%m");
550: }
551: return r;
552: }
553:
554: int
555: delete_filter_rule(const char * ifname, unsigned short eport, int proto)
556: {
557: ipfobj_t wobj, dobj;
558: ipfruleiter_t rule;
559: u_long darray[1000];
560: u_long array[1000];
561: friostat_t fio;
562: frentry_t *fp;
563: int r;
564:
565: if (dev_ipl < 0) {
566: syslog(LOG_ERR, "%s not open", IPL_NAME);
567: return -1;
568: }
569:
570: wobj.ipfo_rev = IPFILTER_VERSION;
571: wobj.ipfo_type = IPFOBJ_IPFSTAT;
572: wobj.ipfo_size = sizeof(fio);
573: wobj.ipfo_ptr = &fio;
574:
575: if (ioctl(dev_ipl, SIOCGETFS, &wobj) == -1) {
576: syslog(LOG_ERR, "ioctl(SIOCGETFS): %m");
577: return -1;
578: }
579:
580: wobj.ipfo_rev = IPFILTER_VERSION;
581: wobj.ipfo_ptr = &rule;
582: wobj.ipfo_size = sizeof(rule);
583: wobj.ipfo_type = IPFOBJ_IPFITER;
584:
585: fp = (frentry_t *)array;
586: fp->fr_dun.fru_data = darray;
587: fp->fr_dsize = sizeof(darray);
588:
589: rule.iri_inout = 0;
590: rule.iri_active = fio.f_active;
591: #if IPFILTER_VERSION > 4011300
592: rule.iri_nrules = 1;
593: rule.iri_v = 4;
594: #endif
595: rule.iri_rule = fp;
596: strlcpy(rule.iri_group, group_name, sizeof(rule.iri_group));
597:
598: dobj.ipfo_rev = IPFILTER_VERSION;
599: dobj.ipfo_size = sizeof(*fp);
600: dobj.ipfo_type = IPFOBJ_FRENTRY;
601:
602: r = -1;
603: do {
604: memset(array, 0xff, sizeof(array));
605:
606: if (ioctl(dev_ipl, SIOCIPFITER, &wobj) == -1) {
607: syslog(LOG_ERR, "ioctl(SIOCIPFITER): %m");
608: break;
609: }
610:
611: if (fp->fr_data != NULL)
612: fp->fr_data = (char *)fp + sizeof(*fp);
613: if ((fp->fr_type & ~FR_T_BUILTIN) == FR_T_IPF &&
614: fp->fr_dport == eport &&
615: fp->fr_proto == proto)
616: {
617: dobj.ipfo_ptr = fp;
618:
619: r = ioctl(dev_ipl, SIOCRMAFR, &dobj);
620: if (r == -1)
621: syslog(LOG_ERR, "ioctl(SIOCRMAFR): %m");
622: break;
623: }
624: } while (fp->fr_next != NULL);
625: return r;
626: }
627:
1.1.1.2 ! misho 628: unsigned short *
! 629: get_portmappings_in_range(unsigned short startport, unsigned short endport,
! 630: int proto, unsigned int * number)
! 631: {
! 632: unsigned short * array;
! 633: unsigned int capacity;
! 634: unsigned short eport;
! 635: ipfgeniter_t iter;
! 636: ipfobj_t obj;
! 637: ipnat_t ipn;
! 638:
! 639: *number = 0;
! 640: if (dev < 0) {
! 641: syslog(LOG_ERR, "%s not open", IPNAT_NAME);
! 642: return NULL;
! 643: }
! 644: capacity = 128;
! 645: array = calloc(capacity, sizeof(unsigned short));
! 646: if(!array)
! 647: {
! 648: syslog(LOG_ERR, "get_portmappings_in_range() : calloc error");
! 649: return NULL;
! 650: }
! 651:
! 652: memset(&obj, 0, sizeof(obj));
! 653: obj.ipfo_rev = IPFILTER_VERSION;
! 654: obj.ipfo_ptr = &iter;
! 655: obj.ipfo_size = sizeof(iter);
! 656: obj.ipfo_type = IPFOBJ_GENITER;
! 657:
! 658: iter.igi_type = IPFGENITER_IPNAT;
! 659: #if IPFILTER_VERSION > 4011300
! 660: iter.igi_nitems = 1;
! 661: #endif
! 662: iter.igi_data = &ipn;
! 663:
! 664: do {
! 665: if (ioctl(dev, SIOCGENITER, &obj) == -1) {
! 666: syslog(LOG_ERR, "%s:ioctl(SIOCGENITER): %m",
! 667: "get_portmappings_in_range");
! 668: break;
! 669: }
! 670:
! 671: if (strcmp(ipn.in_tag.ipt_tag, group_name) != 0)
! 672: continue;
! 673:
! 674: eport = ntohs(ipn.in_pmin);
! 675: if( (eport == ntohs(ipn.in_pmax))
! 676: && (ipn.in_p == proto)
! 677: && (startport <= eport) && (eport <= endport) )
! 678: {
! 679: if(*number >= capacity)
! 680: {
! 681: /* need to increase the capacity of the array */
! 682: capacity += 128;
! 683: array = realloc(array, sizeof(unsigned short)*capacity);
! 684: if(!array)
! 685: {
! 686: syslog(LOG_ERR, "get_portmappings_in_range() : realloc(%lu) error", sizeof(unsigned short)*capacity);
! 687: *number = 0;
! 688: return NULL;
! 689: }
! 690: }
! 691: array[*number] = eport;
! 692: (*number)++;
! 693: }
! 694: } while (ipn.in_next != NULL);
! 695: return array;
! 696: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>