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>