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