Annotation of embedaddon/miniupnpd/pf/obsdrdr.c, revision 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>