Annotation of embedaddon/miniupnpd/ipfw/ipfwrdr.c, revision 1.1.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>