Annotation of embedaddon/miniupnpd/ipfw/ipfwrdr.c, revision 1.1
1.1 ! misho 1: /*
! 2: * MiniUPnP project
! 3: * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
! 4: * (c) 2009 Jardel Weyrich
! 5: * This software is subject to the conditions detailed
! 6: * in the LICENCE file provided within the distribution
! 7: */
! 8:
! 9: #include <sys/param.h>
! 10: #include <sys/types.h>
! 11: #include <sys/file.h>
! 12:
! 13: //
! 14: // This is a workaround for <sys/uio.h> troubles on FreeBSD, HPUX, OpenBSD.
! 15: // Needed here because on some systems <sys/uio.h> gets included by things
! 16: // like <sys/socket.h>
! 17: //
! 18: #ifndef _KERNEL
! 19: # define ADD_KERNEL
! 20: # define _KERNEL
! 21: # define KERNEL
! 22: #endif
! 23: #ifdef __OpenBSD__
! 24: struct file;
! 25: #endif
! 26: #include <sys/uio.h>
! 27: #ifdef ADD_KERNEL
! 28: # undef _KERNEL
! 29: # undef KERNEL
! 30: #endif
! 31:
! 32: #include <sys/time.h>
! 33: #include <sys/socket.h>
! 34: #include <sys/syslog.h>
! 35: #include <sys/ioctl.h>
! 36: #include <net/if.h>
! 37: #if __FreeBSD_version >= 300000
! 38: # include <net/if_var.h>
! 39: #endif
! 40: #include <netinet/in.h>
! 41: #include <netinet/in_systm.h>
! 42: #include <netinet/ip.h>
! 43: #include <netinet/ip_icmp.h>
! 44: #include <netinet/tcp.h>
! 45: #include <netinet/udp.h>
! 46: #include <arpa/inet.h>
! 47:
! 48: #include <sys/types.h>
! 49: #include <sys/queue.h>
! 50: #include <sys/socket.h>
! 51: #include <errno.h>
! 52: #include <limits.h>
! 53: #include <netdb.h>
! 54: #include <stdlib.h>
! 55: #include <fcntl.h>
! 56: #include <syslog.h>
! 57: #include <stddef.h>
! 58: #include <stdio.h>
! 59: #include <strings.h>
! 60: #include <string.h>
! 61: #include <unistd.h>
! 62: #include <netinet/ip_fw.h>
! 63: #include "ipfwaux.h"
! 64:
! 65: #include "../config.h"
! 66: #include "../upnpglobalvars.h"
! 67:
! 68:
! 69: int init_redirect(void) {
! 70: ipfw_exec(IP_FW_INIT, NULL, 0);
! 71: return 0;
! 72: }
! 73:
! 74: void shutdown_redirect(void) {
! 75: ipfw_exec(IP_FW_TERM, NULL, 0);
! 76: }
! 77:
! 78: int add_redirect_rule2(
! 79: const char * ifname,
! 80: unsigned short eport,
! 81: const char * iaddr,
! 82: unsigned short iport,
! 83: int proto,
! 84: const char * desc)
! 85: {
! 86: struct ip_fw rule;
! 87:
! 88: if (ipfw_validate_protocol(proto) < 0)
! 89: return -1;
! 90: if (ipfw_validate_ifname(ifname) < 0)
! 91: return -1;
! 92:
! 93: memset(&rule, 0, sizeof(struct ip_fw));
! 94: rule.version = IP_FW_CURRENT_API_VERSION;
! 95: //rule.fw_number = 1000; // rule number
! 96: rule.context = (void *)desc; // TODO keep this?
! 97: rule.fw_prot = proto; // protocol
! 98: rule.fw_flg |= IP_FW_F_IIFACE; // interfaces to check
! 99: rule.fw_flg |= IP_FW_F_IIFNAME; // interfaces to check by name
! 100: rule.fw_flg |= (IP_FW_F_IN | IP_FW_F_OUT); // packet direction
! 101: rule.fw_flg |= IP_FW_F_FWD; // forward action
! 102: #ifdef USE_IFNAME_IN_RULES
! 103: if (ifname != NULL) {
! 104: strcpy(rule.fw_in_if.fu_via_if.name, ifname); // src interface
! 105: rule.fw_in_if.fu_via_if.unit = -1;
! 106: }
! 107: #endif
! 108: if (inet_aton(iaddr, &rule.fw_out_if.fu_via_ip) == 0) {
! 109: syslog(LOG_ERR, "inet_aton(): %m");
! 110: return -1;
! 111: }
! 112: memcpy(&rule.fw_dst, &rule.fw_out_if.fu_via_ip, sizeof(struct in_addr));
! 113: memcpy(&rule.fw_fwd_ip.sin_addr, &rule.fw_out_if.fu_via_ip, sizeof(struct in_addr));
! 114: rule.fw_dmsk.s_addr = INADDR_BROADCAST;
! 115: IP_FW_SETNDSTP(&rule, 1); // number of external ports
! 116: rule.fw_uar.fw_pts[0] = eport; // external port
! 117: rule.fw_fwd_ip.sin_port = iport; // internal port
! 118:
! 119: return ipfw_exec(IP_FW_ADD, &rule, sizeof(rule));
! 120: }
! 121:
! 122: /* get_redirect_rule()
! 123: * return value : 0 success (found)
! 124: * -1 = error or rule not found */
! 125: int get_redirect_rule(
! 126: const char * ifname,
! 127: unsigned short eport,
! 128: int proto,
! 129: char * iaddr,
! 130: int iaddrlen,
! 131: unsigned short * iport,
! 132: char * desc,
! 133: int desclen,
! 134: u_int64_t * packets,
! 135: u_int64_t * bytes)
! 136: {
! 137: int i, count_rules, total_rules = 0;
! 138: struct ip_fw * rules = NULL;
! 139:
! 140: if (ipfw_validate_protocol(proto) < 0)
! 141: return -1;
! 142: if (ipfw_validate_ifname(ifname) < 0)
! 143: return -1;
! 144:
! 145: do {
! 146: count_rules = ipfw_fetch_ruleset(&rules, &total_rules, 10);
! 147: if (count_rules < 0)
! 148: goto error;
! 149: } while (count_rules == 10);
! 150:
! 151: for (i=0; i<total_rules-1; i++) {
! 152: const struct ip_fw const * ptr = &rules[i];
! 153: if (proto == ptr->fw_prot && eport == ptr->fw_uar.fw_pts[0]) {
! 154: if (packets != NULL)
! 155: *packets = ptr->fw_pcnt;
! 156: if (bytes != NULL)
! 157: *bytes = ptr->fw_bcnt;
! 158: if (iport != NULL)
! 159: *iport = ptr->fw_fwd_ip.sin_port;
! 160: if (desc != NULL && desclen > 0)
! 161: strlcpy(desc, "", desclen); // TODO should we copy ptr->context?
! 162: if (iaddr != NULL && iaddrlen > 0) {
! 163: if (inet_ntop(AF_INET, &ptr->fw_out_if.fu_via_ip, iaddr, iaddrlen) == NULL) {
! 164: syslog(LOG_ERR, "inet_ntop(): %m");
! 165: goto error;
! 166: }
! 167: }
! 168: // And what if we found more than 1 matching rule?
! 169: ipfw_free_ruleset(&rules);
! 170: return 0;
! 171: }
! 172: }
! 173:
! 174: error:
! 175: if (rules != NULL)
! 176: ipfw_free_ruleset(&rules);
! 177: return -1;
! 178: }
! 179:
! 180: int delete_redirect_rule(
! 181: const char * ifname,
! 182: unsigned short eport,
! 183: int proto)
! 184: {
! 185: int i, count_rules, total_rules = 0;
! 186: struct ip_fw * rules = NULL;
! 187:
! 188: if (ipfw_validate_protocol(proto) < 0)
! 189: return -1;
! 190: if (ipfw_validate_ifname(ifname) < 0)
! 191: return -1;
! 192:
! 193: do {
! 194: count_rules = ipfw_fetch_ruleset(&rules, &total_rules, 10);
! 195: if (count_rules < 0)
! 196: goto error;
! 197: } while (count_rules == 10);
! 198:
! 199: for (i=0; i<total_rules-1; i++) {
! 200: const struct ip_fw const * ptr = &rules[i];
! 201: if (proto == ptr->fw_prot && eport == ptr->fw_uar.fw_pts[0]) {
! 202: if (ipfw_exec(IP_FW_DEL, (struct ip_fw *)ptr, sizeof(*ptr)) < 0)
! 203: goto error;
! 204: // And what if we found more than 1 matching rule?
! 205: ipfw_free_ruleset(&rules);
! 206: return 0;
! 207: }
! 208: }
! 209:
! 210: error:
! 211: if (rules != NULL)
! 212: ipfw_free_ruleset(&rules);
! 213: return -1;
! 214: }
! 215:
! 216: int add_filter_rule2(
! 217: const char * ifname,
! 218: const char * iaddr,
! 219: unsigned short eport,
! 220: unsigned short iport,
! 221: int proto,
! 222: const char * desc)
! 223: {
! 224: return -1;
! 225: }
! 226:
! 227: int delete_filter_rule(
! 228: const char * ifname,
! 229: unsigned short eport,
! 230: int proto)
! 231: {
! 232: return -1;
! 233: }
! 234:
! 235: int get_redirect_rule_by_index(
! 236: int index,
! 237: char * ifname,
! 238: unsigned short * eport,
! 239: char * iaddr,
! 240: int iaddrlen,
! 241: unsigned short * iport,
! 242: int * proto,
! 243: char * desc,
! 244: int desclen,
! 245: u_int64_t * packets,
! 246: u_int64_t * bytes)
! 247: {
! 248: int total_rules = 0;
! 249: struct ip_fw * rules = NULL;
! 250:
! 251: if (index < 0) // TODO shouldn't we also validate the maximum?
! 252: return -1;
! 253:
! 254: ipfw_fetch_ruleset(&rules, &total_rules, index + 1);
! 255:
! 256: if (total_rules == index + 1) {
! 257: const struct ip_fw const * ptr = &rules[index];
! 258: if (proto != NULL)
! 259: *proto = ptr->fw_prot;
! 260: if (eport != NULL)
! 261: *eport = ptr->fw_uar.fw_pts[0];
! 262: if (iport != NULL)
! 263: *iport = ptr->fw_fwd_ip.sin_port;
! 264: if (ifname != NULL)
! 265: strlcpy(ifname, ptr->fw_in_if.fu_via_if.name, IFNAMSIZ);
! 266: if (packets != NULL)
! 267: *packets = ptr->fw_pcnt;
! 268: if (bytes != NULL)
! 269: *bytes = ptr->fw_bcnt;
! 270: if (iport != NULL)
! 271: *iport = ptr->fw_fwd_ip.sin_port;
! 272: if (desc != NULL && desclen > 0)
! 273: strlcpy(desc, "", desclen); // TODO should we copy ptr->context?
! 274: if (iaddr != NULL && iaddrlen > 0) {
! 275: if (inet_ntop(AF_INET, &ptr->fw_out_if.fu_via_ip, iaddr, iaddrlen) == NULL) {
! 276: syslog(LOG_ERR, "inet_ntop(): %m");
! 277: goto error;
! 278: }
! 279: }
! 280: ipfw_free_ruleset(&rules);
! 281: return 0;
! 282: }
! 283:
! 284: error:
! 285: if (rules != NULL)
! 286: ipfw_free_ruleset(&rules);
! 287: return -1;
! 288: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>