Annotation of embedaddon/miniupnpd/upnppinhole.c, revision 1.1.1.1

1.1       misho       1: /* $Id: upnppinhole.c,v 1.4 2012/05/08 20:41:45 nanard Exp $ */
                      2: /* MiniUPnP project
                      3:  * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
                      4:  * (c) 2006-2012 Thomas Bernard
                      5:  * This software is subject to the conditions detailed
                      6:  * in the LICENCE file provided within the distribution */
                      7: 
                      8: #include <stdlib.h>
                      9: #include <string.h>
                     10: #include <syslog.h>
                     11: #include <sys/types.h>
                     12: #include <sys/socket.h>
                     13: #include <netinet/in.h>
                     14: #include <net/if.h>
                     15: #include <arpa/inet.h>
                     16: 
                     17: #include <stdio.h>
                     18: #include <ctype.h>
                     19: #include <unistd.h>
                     20: 
                     21: #include "macros.h"
                     22: #include "config.h"
                     23: #include "upnpredirect.h"
                     24: #include "upnpglobalvars.h"
                     25: #include "upnpevents.h"
                     26: #if defined(USE_NETFILTER)
                     27: #include "netfilter/iptpinhole.h"
                     28: #endif
                     29: #if defined(USE_PF)
                     30: #include "pf/pfpinhole.h"
                     31: #endif
                     32: #if defined(USE_IPF)
                     33: #endif
                     34: #if defined(USE_IPFW)
                     35: #endif
                     36: 
                     37: #ifdef ENABLE_6FC_SERVICE
                     38: #if 0
                     39: int
                     40: upnp_check_outbound_pinhole(int proto, int * timeout)
                     41: {
                     42:        int s, tmptimeout, tmptime_out;
                     43:        switch(proto)
                     44:        {
                     45:                case IPPROTO_UDP:
                     46:                        s = retrieve_timeout("udp_timeout", timeout);
                     47:                        return s;
                     48:                        break;
                     49:                case IPPROTO_UDPLITE:
                     50:                        s = retrieve_timeout("udp_timeout_stream", timeout);
                     51:                        return s;
                     52:                        break;
                     53:                case IPPROTO_TCP:
                     54:                        s = retrieve_timeout("tcp_timeout_established", timeout);
                     55:                        return s;
                     56:                        break;
                     57:                case 65535:
                     58:                        s = retrieve_timeout("udp_timeout", timeout);
                     59:                        s = retrieve_timeout("udp_timeout_stream", &tmptimeout);
                     60:                        s = retrieve_timeout("tcp_timeout_established", &tmptime_out);
                     61:                        if(tmptimeout<tmptime_out)
                     62:                        {
                     63:                                if(tmptimeout<*timeout)
                     64:                                        *timeout = tmptimeout;
                     65:                        }
                     66:                        else
                     67:                        {
                     68:                                if(tmptime_out<*timeout)
                     69:                                        *timeout = tmptimeout;
                     70:                        }
                     71:                        return s;
                     72:                        break;
                     73:                default:
                     74:                        return -5;
                     75:                        break;
                     76:        }
                     77:        return 0;
                     78: }
                     79: #endif
                     80: 
                     81: /* upnp_add_inboundpinhole()
                     82:  * returns: 0 on success
                     83:  *          -1 failed to add pinhole
                     84:  *          -2 already created
                     85:  *          -3 inbound pinhole disabled
                     86:  * TODO : return uid on success (positive) or error value (negative)
                     87:  */
                     88: int
                     89: upnp_add_inboundpinhole(const char * raddr,
                     90:                         unsigned short rport,
                     91:                         const char * iaddr,
                     92:                         unsigned short iport,
                     93:                         int proto,
                     94:                         unsigned int leasetime,
                     95:                         int * uid)
                     96: {
                     97:        int r;
                     98:        time_t current;
                     99:        unsigned int timestamp;
                    100:        struct in6_addr address;
                    101: 
                    102:        if(inet_pton(AF_INET6, iaddr, &address) < 0)
                    103:        {
                    104:                syslog(LOG_ERR, "inet_pton(%s) : %m", iaddr);
                    105:                return 0;
                    106:        }
                    107:        current = time(NULL);
                    108:        timestamp = current + leasetime;
                    109:        r = 0;
                    110: 
                    111: #if 0
                    112:        if(r == 1 && strcmp(iaddr, iaddr_old)==0 && iport==iport_old)
                    113:        {
                    114:                syslog(LOG_INFO, "Pinhole for inbound traffic from [%s]:%hu to [%s]:%hu with protocol %s already done. Updating it.", raddr, rport, iaddr_old, iport_old, protocol);
                    115:                t = upnp_update_inboundpinhole(idfound, leaseTime);
                    116:                *uid = atoi(idfound);
                    117:                return t;
                    118:        }
                    119:        else
                    120: #endif
                    121:        {
                    122: #if defined(USE_PF) || defined(USE_NETFILTER)
                    123:                *uid = add_pinhole (0/*ext_if_name*/, raddr, rport,
                    124:                                    iaddr, iport, proto, timestamp);
                    125:                return 1;
                    126: #else
                    127:                return -42;     /* not implemented */
                    128: #endif
                    129:        }
                    130: }
                    131: 
                    132: #if 0
                    133: int
                    134: upnp_add_inboundpinhole_internal(const char * raddr, unsigned short rport,
                    135:                        const char * iaddr, unsigned short iport,
                    136:                        const char * proto, int * uid)
                    137: {
                    138:        int c = 9999;
                    139:        char cmd[256], cmd_raw[256], cuid[42];
                    140: #if 0
                    141:        static const char cmdval_full_udptcp[] = "ip6tables -I %s %d -p %s -i %s -s %s --sport %hu -d %s --dport %hu -j ACCEPT";
                    142:        static const char cmdval_udptcp[] = "ip6tables -I %s %d -p %s -i %s --sport %hu -d %s --dport %hu -j ACCEPT";
                    143:        static const char cmdval_full_udplite[] = "ip6tables -I %s %d -p %s -i %s -s %s -d %s -j ACCEPT";
                    144:        static const char cmdval_udplite[] = "ip6tables -I %s %d -p %s -i %s -d %s -j ACCEPT";
                    145:        // raw table command
                    146:        static const char cmdval_full_udptcp_raw[] = "ip6tables -t raw -I PREROUTING %d -p %s -i %s -s %s --sport %hu -d %s --dport %hu -j TRACE";
                    147:        static const char cmdval_udptcp_raw[] = "ip6tables -t raw -I PREROUTING %d -p %s -i %s --sport %hu -d %s --dport %hu -j TRACE";
                    148:        static const char cmdval_full_udplite_raw[] = "ip6tables -t raw -I PREROUTING %d -p %s -i %s -s %s -d %s -j TRACE";
                    149:        static const char cmdval_udplite_raw[] = "ip6tables -t raw -I PREROUTING %d -p %s -i %s -d %s -j TRACE";
                    150: #endif
                    151:        /*printf("%s\n", raddr);*/
                    152:        if(raddr!=NULL)
                    153:        {
                    154: #ifdef IPPROTO_UDPLITE
                    155:                if(atoi(proto) == IPPROTO_UDPLITE)
                    156:                {
                    157:        /*              snprintf(cmd, sizeof(cmd), cmdval_full_udplite, miniupnpd_forward_chain, line_number, proto, ext_if_name, raddr, iaddr);
                    158:                        snprintf(cmd_raw, sizeof(cmd_raw), cmdval_full_udplite_raw, line_number, proto, ext_if_name, raddr, iaddr);*/
                    159:                }
                    160:                else
                    161: #endif
                    162:                {
                    163:        /*              snprintf(cmd, sizeof(cmd), cmdval_full_udptcp, miniupnpd_forward_chain, line_number, proto, ext_if_name, raddr, rport, iaddr, iport);
                    164:                        snprintf(cmd_raw, sizeof(cmd_raw), cmdval_full_udptcp_raw, line_number, proto, ext_if_name, raddr, rport, iaddr, iport);*/
                    165:                }
                    166:        }
                    167:        else
                    168:        {
                    169: #ifdef IPPROTO_UDPLITE
                    170:                if(atoi(proto) == IPPROTO_UDPLITE)
                    171:                {
                    172:                        /*snprintf(cmd, sizeof(cmd), cmdval_udplite, miniupnpd_forward_chain, line_number, proto, ext_if_name, iaddr);
                    173:                        snprintf(cmd_raw, sizeof(cmd_raw), cmdval_udplite_raw, line_number, proto, ext_if_name, iaddr);*/
                    174:                }
                    175:                else
                    176: #endif
                    177:                {
                    178:                        /*snprintf(cmd, sizeof(cmd), cmdval_udptcp, miniupnpd_forward_chain, line_number, proto, ext_if_name, rport, iaddr, iport);
                    179:                        snprintf(cmd_raw, sizeof(cmd_raw), cmdval_udptcp_raw, line_number, proto, ext_if_name, rport, iaddr, iport);
                    180: */
                    181:                }
                    182:        }
                    183: #ifdef DEBUG
                    184:        syslog(LOG_INFO, "Adding following ip6tables rule:");
                    185:        syslog(LOG_INFO, "  -> %s", cmd);
                    186:        syslog(LOG_INFO, "  -> %s", cmd_raw);
                    187: #endif
                    188:        /* TODO Add a better checking error.*/
                    189:        if(system(cmd) < 0 || system(cmd_raw) < 0)
                    190:        {
                    191:                return 0;
                    192:        }
                    193:        srand(time(NULL));
                    194:        snprintf(cuid, sizeof(cuid), "%.4d", rand()%c);
                    195:        *uid = atoi(cuid);
                    196:        printf("\t_add_ uid: %s\n", cuid);
                    197:        return 1;
                    198: }
                    199: #endif
                    200: 
                    201: /* upnp_get_pinhole_info()
                    202:  * return values :
                    203:  *   0   OK
                    204:  *  -1   Internal error
                    205:  *  -2   NOT FOUND (no such entry)
                    206:  *  .. 
                    207:  *  -42  Not implemented
                    208:  */
                    209: int
                    210: upnp_get_pinhole_info(unsigned short uid,
                    211:                       char * raddr, int raddrlen,
                    212:                       unsigned short * rport,
                    213:                       char * iaddr, int iaddrlen,
                    214:                       unsigned short * iport,
                    215:                       int * proto,
                    216:                       unsigned int * leasetime,
                    217:                       unsigned int * packets)
                    218: {
                    219:        /* Call Firewall specific code to get IPv6 pinhole infos */
                    220: #if defined(USE_PF) || defined(USE_NETFILTER)
                    221:        int r;
                    222:        unsigned int timestamp;
                    223:        u_int64_t packets_tmp;
                    224:        /*u_int64_t bytes_tmp;*/
                    225: 
                    226:        r = get_pinhole_info(uid, raddr, raddrlen, rport,
                    227:                             iaddr, iaddrlen, iport, proto,
                    228:                             leasetime ? &timestamp : NULL,
                    229:                             packets ? &packets_tmp : NULL,
                    230:                             NULL/*&bytes_tmp*/);
                    231:        if(r >= 0) {
                    232:                if(leasetime) {
                    233:                        time_t current_time;
                    234:                        current_time = time(NULL);
                    235:                        if(timestamp > (unsigned int)current_time)
                    236:                                *leasetime = timestamp - current_time;
                    237:                        else
                    238:                                *leasetime = 0;
                    239:                }
                    240:                if(packets)
                    241:                        *packets = (unsigned int)packets_tmp;
                    242:        }
                    243:        return r;
                    244: #else
                    245:        UNUSED(uid);
                    246:        UNUSED(raddr); UNUSED(raddrlen); UNUSED(rport);
                    247:        UNUSED(iaddr); UNUSED(iaddrlen); UNUSED(iport);
                    248:        UNUSED(proto); UNUSED(leasetime); UNUSED(packets);
                    249:        return -42;     /* not implemented */
                    250: #endif
                    251: }
                    252: 
                    253: int
                    254: upnp_update_inboundpinhole(unsigned short uid, unsigned int leasetime)
                    255: {
                    256: #if defined(USE_PF) || defined(USE_NETFILTER)
                    257:        unsigned int timestamp;
                    258: 
                    259:        timestamp = time(NULL) + leasetime;
                    260:        return update_pinhole(uid, timestamp);
                    261: #else
                    262:        UNUSED(uid); UNUSED(leasetime);
                    263: 
                    264:        return -42; /* not implemented */
                    265: #endif
                    266: }
                    267: 
                    268: int
                    269: upnp_delete_inboundpinhole(unsigned short uid)
                    270: {
                    271: #if defined(USE_PF) || defined(USE_NETFILTER)
                    272:        return delete_pinhole(uid);
                    273: #else
                    274:        UNUSED(uid);
                    275: 
                    276:        return -1;
                    277: #endif
                    278: }
                    279: 
                    280: #if 0
                    281: /*
                    282:  * Result:
                    283:  *      1: Found Result
                    284:  *     -4: No result
                    285:  *     -5: Result in another table
                    286:  *     -6: Result in another chain
                    287:  *     -7: Result in a chain not a rule
                    288: */
                    289: int
                    290: upnp_check_pinhole_working(const char * uid,
                    291:                            char * eaddr,
                    292:                            char * iaddr,
                    293:                            unsigned short * eport,
                    294:                            unsigned short * iport,
                    295:                            char * protocol,
                    296:                            int * rulenum_used)
                    297: {
                    298:        /* TODO : to be implemented */
                    299: #if 0
                    300:        FILE * fd;
                    301:        time_t expire = time(NULL);
                    302:        char buf[1024], filename[] = "/var/log/kern.log", expire_time[32]="";
                    303:        int res = -4, str_len;
                    304: 
                    305:        str_len = strftime(expire_time, sizeof(expire_time), "%b %d %H:%M:%S", localtime(&expire));
                    306: 
                    307:        fd = fopen(filename, "r");
                    308:        if (fd==NULL)
                    309:        {
                    310:                syslog(LOG_ERR, "Get_rule: could not open file: %s", filename);
                    311:                return -1;
                    312:        }
                    313: 
                    314:        syslog(LOG_INFO, "Get_rule: Starting getting info in file %s for %s\n", filename, uid);
                    315:        buf[sizeof(buf)-1] = 0;
                    316:        while(fgets(buf, sizeof(buf)-1, fd) != NULL && res != 1)
                    317:        {
                    318:                //printf("line: %s\n", buf);
                    319:                char * r, * t, * c, * p;
                    320:                // looking for something like filter:FORWARD:rule: or filter:MINIUPNPD:rule:
                    321:                r = strstr(buf, ":rule:");
                    322:                p = strstr(buf, ":policy:");
                    323:                t = strstr(buf, "TRACE:"); // table pointeur
                    324:                t += 7;
                    325:                c = t + 7; // chain pointeur
                    326:                if(r)
                    327:                {
                    328:                        printf("\t** Found %.*s\n", 24 ,t);
                    329:                        char * src, * dst, * sport, * dport, * proto, * line;
                    330:                        char time[15]="", src_addr[40], dst_addr[40], proto_tmp[8];
                    331:                        int proto_int;
                    332:                        strncpy(time, buf, sizeof(time));
                    333:                        /*if(compare_time(time, expire_time)<0)
                    334:                        {
                    335:                                printf("\t\tNot corresponding time\n");
                    336:                                continue;
                    337:                        }*/
                    338: 
                    339:                        line = r + 6;
                    340:                        printf("\trule line = %d\n", atoi(line));
                    341: 
                    342:                        src = strstr(buf, "SRC=");
                    343:                        src += 4;
                    344:                        snprintf(src_addr, sizeof(src_addr), "%.*s", 39, src);
                    345: #if 0
                    346:                        del_char(src_addr);
                    347:                        add_char(src_addr);
                    348: #endif
                    349: 
                    350:                        dst = strstr(buf, "DST=");
                    351:                        dst += 4;
                    352:                        snprintf(dst_addr, sizeof(dst_addr), "%.*s", 39, dst);
                    353: #if 0
                    354:                        del_char(dst_addr);
                    355:                        add_char(dst_addr);
                    356: #endif
                    357: 
                    358:                        proto = strstr(buf, "PROTO=");
                    359:                        proto += 6;
                    360:                        proto_int = atoi(protocol);
                    361:                        if(proto_int == IPPROTO_UDP)
                    362:                                strcpy(proto_tmp, "UDP");
                    363:                        else if(proto_int == IPPROTO_TCP)
                    364:                                strcpy(proto_tmp, "TCP");
                    365: #ifdef IPPROTO_UDPLITE
                    366:                        else if(proto_int == IPPROTO_UDPLITE)
                    367:                                strcpy(proto_tmp, "UDPLITE");
                    368: #endif
                    369:                        else
                    370:                                strcpy(proto_tmp, "UnsupportedProto");
                    371: 
                    372:        //              printf("\tCompare eaddr: %s // protocol: %s\n\t     to  addr: %s // protocol: %.*s\n", eaddr, proto_tmp, src_addr, strlen(proto_tmp), proto);
                    373:        //              printf("\tCompare iaddr: %s // protocol: %s\n\t     to  addr: %s // protocol: %.*s\n", iaddr, proto_tmp, dst_addr, strlen(proto_tmp), proto);
                    374:                        // TODO Check time
                    375:                        // Check that the paquet found in trace correspond to the one we are looking for
                    376:                        if( /*(strcmp(eaddr, src_addr) == 0) &&*/ (strcmp(iaddr, dst_addr) == 0) && (strncmp(proto_tmp, proto, strlen(proto_tmp))==0))
                    377:                        {
                    378:                                sport = strstr(buf, "SPT=");
                    379:                                sport += 4;
                    380:                                dport = strstr(buf, "DPT=");
                    381:                                dport += 4;
                    382:                                printf("\tCompare eport: %hu\n\t     to   port: %d\n", *eport, atoi(sport));
                    383:                                printf("\tCompare iport: %hu\n\t     to   port: %d\n", *iport, atoi(dport));
                    384:                                if(/*eport != atoi(sport) &&*/ *iport != atoi(dport))
                    385:                                {
                    386:                                        printf("\t\tPort not corresponding\n");
                    387:                                        continue;
                    388:                                }
                    389:                                printf("\ttable found: %.*s\n", 6, t);
                    390:                                printf("\tchain found: %.*s\n", 9, c);
                    391:                                // Check that the table correspond to the filter table
                    392:                                if(strncmp(t, "filter", 6)==0)
                    393:                                {
                    394:                                        // Check that the table correspond to the MINIUPNP table
                    395:                                        if(strncmp(c, "MINIUPNPD", 9)==0)
                    396:                                        {
                    397:                                                *rulenum_used = atoi(line);
                    398:                                                res = 1;
                    399:                                        }
                    400:                                        else
                    401:                                        {
                    402:                                                res = -6;
                    403:                                                continue;
                    404:                                        }
                    405:                                }
                    406:                                else
                    407:                                {
                    408:                                        res = -5;
                    409:                                        continue;
                    410:                                }
                    411:                        }
                    412:                        else
                    413:                        {
                    414:                                printf("Packet information not corresponding\n");
                    415:                                continue;
                    416:                        }
                    417:                }
                    418:                if(!r && p)
                    419:                {
                    420:                        printf("\t** Policy case\n");
                    421:                        char * src, * dst, * sport, * dport, * proto, * line;
                    422:                        char time[15], src_addr[40], dst_addr[40], proto_tmp[8];
                    423:                        int proto_int;
                    424:                        strncpy(time, buf, sizeof(time));
                    425:                        /*if(compare_time(time, expire_time)<0)
                    426:                        {
                    427:                                printf("\t\tNot corresponding time\n");
                    428:                                continue;
                    429:                        }*/
                    430: 
                    431:                        line = p + 8;
                    432:                        printf("\trule line = %d\n", atoi(line));
                    433: 
                    434:                        src = strstr(buf, "SRC=");
                    435:                        src += 4;
                    436:                        snprintf(src_addr, sizeof(src_addr), "%.*s", 39, src);
                    437: #if 0
                    438:                        del_char(src_addr);
                    439:                        add_char(src_addr);
                    440: #endif
                    441: 
                    442:                        dst = strstr(buf, "DST=");
                    443:                        dst += 4;
                    444:                        snprintf(dst_addr, sizeof(dst_addr), "%.*s", 39, dst);
                    445: #if 0
                    446:                        del_char(dst_addr);
                    447:                        add_char(dst_addr);
                    448: #endif
                    449: 
                    450:                        proto = strstr(buf, "PROTO=");
                    451:                        proto += 6;
                    452:                        proto_int = atoi(protocol);
                    453:                        if(proto_int == IPPROTO_UDP)
                    454:                                strcpy(proto_tmp, "UDP");
                    455:                        else if(proto_int == IPPROTO_TCP)
                    456:                                strcpy(proto_tmp, "TCP");
                    457: #ifdef IPPROTO_UDPLITE
                    458:                        else if(proto_int == IPPROTO_UDPLITE)
                    459:                                strcpy(proto_tmp, "UDPLITE");
                    460: #endif
                    461:                        else
                    462:                                strcpy(proto_tmp, "UnsupportedProto");
                    463: 
                    464:        //              printf("\tCompare eaddr: %s // protocol: %s\n\t     to  addr: %s // protocol: %.*s\n", eaddr, proto_tmp, src_addr, strlen(proto_tmp), proto);
                    465:        //              printf("\tCompare iaddr: %s // protocol: %s\n\t     to  addr: %s // protocol: %.*s\n", iaddr, proto_tmp, dst_addr, strlen(proto_tmp), proto);
                    466:                        // Check that the paquet found in trace correspond to the one we are looking for
                    467:                        if( (strcmp(eaddr, src_addr) == 0) && (strcmp(iaddr, dst_addr) == 0) && (strncmp(proto_tmp, proto, 5)==0))
                    468:                        {
                    469:                                sport = strstr(buf, "SPT=");
                    470:                                sport += 4;
                    471:                                dport = strstr(buf, "DPT=");
                    472:                                dport += 4;
                    473:                                printf("\tCompare eport: %hu\n\t     to   port: %d\n", *eport, atoi(sport));
                    474:                                printf("\tCompare iport: %hu\n\t     to   port: %d\n", *iport, atoi(dport));
                    475:                                if(*eport != atoi(sport) && *iport != atoi(dport))
                    476:                                {
                    477:                                        printf("\t\tPort not corresponding\n");
                    478:                                        continue;
                    479:                                }
                    480:                                else
                    481:                                {
                    482:                                        printf("Find a corresponding policy trace in the chain: %.*s\n", 10, c);
                    483:                                        res = -7;
                    484:                                        continue;
                    485:                                }
                    486:                        }
                    487:                        else
                    488:                                continue;
                    489:                }
                    490:        }
                    491:        fclose(fd);
                    492:        return res;
                    493: #else
                    494:        return -42;     /* to be implemented */
                    495: #endif
                    496: }
                    497: #endif
                    498: 
                    499: int
                    500: upnp_clean_expired_pinholes(unsigned int * next_timestamp)
                    501: {
                    502: #if defined(USE_PF) || defined(USE_NETFILTER)
                    503:        return clean_pinhole_list(next_timestamp);
                    504: #else
                    505:        UNUSED(next_timestamp);
                    506: 
                    507:        return 0;       /* nothing to do */
                    508: #endif
                    509: }
                    510: #endif
                    511: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>