Changeset 100

Show
Ignore:
Timestamp:
07/03/07 19:48:26 (1 year ago)
Author:
gotoh
Message:

Allow domain name based item in xxxx_DIRECT environment variable.
No more unwanted local resolving of target hostname to judge direct or not.
Fix to terminate the program on connection timeout.

(downcase): return converted string.
(ADDRPAIR): hold target host name to eliminate resolving IP address.
(add_direct_host): New function.
(initialize_direct_addr): Accept domain notation.
(is_direct_address): Change argument type.
(domain_match): New function.
(is_direct_name): New function.
(check_direct): New function.
(open_connection): Do not resolve address for judge direct or not.
(sig_timeout): Bug fix to exit program on timeout. Thanks to Alessandro.
(main): Use check_direct() here.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/connect.c

    r99 r100  
    530530} 
    531531 
    532 void 
    533 downcase( char *buf ) 
    534 
     532char * 
     533downcase( char *str ) 
     534
     535    char *buf = str; 
    535536    while ( *buf ) { 
    536537        if ( isupper(*buf) ) 
     
    538539        buf++; 
    539540    } 
     541    return str;                                 /* return converted arg */ 
    540542} 
    541543 
     
    790792    struct in_addr addr; 
    791793    struct in_addr mask; 
     794    char *name; 
    792795    int negative; 
    793796}; 
     
    818821    mask_addr(&iaddr, mask, sizeof(iaddr)); 
    819822    s = strdup(inet_ntoa(iaddr)); 
    820     debug("adding direct address entry: %s/%s\n", s, inet_ntoa(*mask)); 
     823    debug("adding direct addr entry: %s%s/%s\n", 
     824          negative? "!": "", s, inet_ntoa(*mask)); 
    821825    free(s); 
    822826    memcpy( &direct_addr_list[n_direct_addr_list].addr, 
     
    824828    memcpy( &direct_addr_list[n_direct_addr_list].mask, 
    825829            mask, sizeof(*mask)); 
     830    direct_addr_list[n_direct_addr_list].name = NULL; 
    826831    direct_addr_list[n_direct_addr_list].negative = negative; 
    827832    n_direct_addr_list++; 
    828833    return 0; 
    829834} 
     835 
     836 
     837/* add domain/host name entry to direct name table */ 
     838int 
     839add_direct_host( const char *name, int negative) 
     840{ 
     841    if ( MAX_DIRECT_ADDR_LIST <= n_direct_addr_list ) { 
     842        error("direct address table is full!\n"); 
     843        return -1; 
     844    } 
     845    if (*name == '*') 
     846        name++; 
     847    if (*name == '.') 
     848        name++; 
     849    debug("adding direct name entry: %s%s\n", negative? "!": "", name); 
     850    direct_addr_list[n_direct_addr_list].name = downcase(strdup(name)); 
     851    direct_addr_list[n_direct_addr_list].negative = negative; 
     852    n_direct_addr_list++; 
     853    return 0; 
     854} 
     855 
    830856 
    831857int 
     
    845871 
    846872    assert( str != NULL ); 
    847     debug("parsing address pair: '%s'\n", str); 
    848873    addr->s_addr = 0; 
    849874    mask->s_addr = 0; 
     
    949974            add_direct_addr( &addr, &mask, negative ); 
    950975        } else { 
    951             error("invalid addr format in %s: %s\n", envkey, beg); 
     976            add_direct_host( beg, negative ); 
    952977        } 
    953978        if ( next != NULL ) 
     
    966991 
    967992int 
    968 is_direct_address (const struct sockaddr_in *addr) 
    969 
    970     int i; 
    971     struct in_addr saddr, iaddr; 
    972  
    973     saddr = addr->sin_addr; 
     993is_direct_address (const struct in_addr addr) 
     994
     995    int i, neg; 
     996    struct in_addr iaddr; 
    974997 
    975998    /* Note: assume IPV4 address !! */ 
    976999    for (i=0; i<n_direct_addr_list; i++ ) { 
    977         iaddr = saddr; 
     1000        if (direct_addr_list[i].name != NULL) 
     1001            continue;                           /* it's name entry */ 
     1002        neg = direct_addr_list[i].negative; 
     1003        iaddr = addr; 
    9781004        mask_addr( &iaddr, &direct_addr_list[i].mask, 
    9791005                   sizeof(struct in_addr)); 
    9801006        if (cmp_addr(&iaddr, &direct_addr_list[i].addr, 
    9811007                     sizeof(struct in_addr)) == 0) { 
    982             if (direct_addr_list[i].negative) { 
    983                 debug("negative match, addr to be SOCKSify: %s\n", 
    984                       inet_ntoa(saddr)); 
     1008            char *a, *m; 
     1009            a = strdup(inet_ntoa(direct_addr_list[i].addr)); 
     1010            m = strdup(inet_ntoa(direct_addr_list[i].mask)); 
     1011            debug("match with: %s/%s%s\n", a, m, neg? " (negative)": ""); 
     1012            free(a); 
     1013            free(m); 
     1014            return !neg? 1: 0; 
     1015        } 
     1016    } 
     1017    debug("not matched, addr to be relayed: %s\n", inet_ntoa(addr)); 
     1018    return 0;                   /* not direct */ 
     1019
     1020 
     1021 
     1022/* check s1 is ends with s2. 
     1023   return 1 if exact match or domain part match. 
     1024   return 0 if s1 is shorter than s2 or partial match. 
     1025   For example,  
     1026    ends_with("bar.com", "bar.com")        => 1 (exact match) 
     1027    ends_with("foo.bar.com", "bar.com")    => 1 (domain match) 
     1028    ends_with("foo.beebar.com", "bar.com") => 0 (partial match) 
     1029    ends_with("bar", "bar.com")            => 0 (shorter) 
     1030 */ 
     1031domain_match(const char *s1, const char *s2) 
     1032
     1033    int len1, len2; 
     1034    const char *tail1, *tail2; 
     1035    len1 = strlen(s1); 
     1036    len2 = strlen(s2); 
     1037    if (len1 < len2 || len1 == 0 || len2 == 0) 
     1038        return 0;                               /* not match */ 
     1039    tail1 = s1 + len1; 
     1040    tail2 = s2 + len2; 
     1041    while (0 < len1 && 0 < len2) { 
     1042        if (*--tail1 != *--tail2) 
     1043            break;                              /* not match */ 
     1044        len1--, len2--; 
     1045    } 
     1046    if (len2 != 0) 
     1047        return 0;                               /* not match */ 
     1048    /* Now exact match, domain match or partial match. 
     1049       Return true if exact or domain match. 
     1050       Or continue checking. */ 
     1051    if (tail1 == s1 || tail1[-1] == '.') 
     1052        return 1;                               /* match! */ 
     1053    return 0;                                   /* not match */ 
     1054
     1055 
     1056/* Check given NAME is ends with one of  
     1057   registered direct name entry. 
     1058   Return 1 if matched, or 0. 
     1059*/ 
     1060int 
     1061is_direct_name (const char *name) 
     1062
     1063    int len, i; 
     1064    const char *tail; 
     1065    debug("checking %s is for direct?\n", name); 
     1066    name = downcase(strdup(name)); 
     1067    len = strlen(name); 
     1068    if (len < 1) 
     1069        return 0;                               /* false */ 
     1070    tail = &name[len]; 
     1071    for (i=0; i<n_direct_addr_list; i++ ) { 
     1072        int dlen, neg; 
     1073        const char *dname; 
     1074        const char *n, *d; 
     1075        dname = direct_addr_list[i].name; 
     1076        if (dname == NULL) 
     1077            continue;                           /* it's addr/mask entry */ 
     1078        neg = direct_addr_list[i].negative; 
     1079        if (domain_match(name, dname)) { 
     1080            debug("match with: %s%s\n", dname, neg? " (negative)": ""); 
     1081            if (neg) { 
    9851082                return 0;       /* not direct */ 
    986             } 
    987             if (!direct_addr_list[i].negative) { 
    988                 debug("positive match, addr to be direct: %s\n", 
    989                       inet_ntoa(saddr)); 
     1083            } else { 
    9901084                return 1;       /* direct*/ 
    9911085            } 
    9921086        } 
    9931087    } 
    994     debug("not matched, addr to be SOCKSified: %s\n", inet_ntoa(saddr)); 
    995     return 0;                   /* not direct */ 
     1088    return 0;                                   /* not matched */ 
     1089
     1090 
     1091/* check to connect to HOST directyly? 
     1092   return 1 if to be direct, 0 for else. */ 
     1093int 
     1094check_direct(const char *host) 
     1095
     1096    struct in_addr addr; 
     1097    addr.s_addr = inet_addr(host); 
     1098    if (addr.s_addr != INADDR_NONE) { 
     1099        /* case of IP address */ 
     1100        if (is_direct_address(addr)) { 
     1101            debug("%s is for direct.\n", host); 
     1102            return 1;                           /* true */ 
     1103        } 
     1104    } else { 
     1105        /* case of hostname */ 
     1106        if (is_direct_name(host)) { 
     1107            debug("%s is for direct.\n", host); 
     1108            return 1;                           /* true */ 
     1109        } 
     1110    } 
     1111    debug("%s is for not direct.\n", host); 
     1112    return 0;                                    /* false */ 
    9961113} 
    9971114 
     
    12301347        debug ("No direct address are specified.\n"); 
    12311348    } else { 
    1232         int i; 
    1233         for ( i=0; i<n_direct_addr_list; i++ ) { 
    1234             char *s1, *s2; 
    1235             s1 = strdup(inet_ntoa(direct_addr_list[i].addr)); 
    1236             s2 = strdup(inet_ntoa(direct_addr_list[i].mask)); 
    1237             debug(" #%d: %c%s/%s\n", i, 
    1238                   (direct_addr_list[i].negative)? '!': ' ', 
    1239                   s1, s2); 
    1240             free(s1); 
    1241             free(s2); 
    1242         } 
     1349        debug ("%d direct address entries.\n", n_direct_addr_list); 
    12431350    } 
    12441351 
     
    16011708sig_timeout(void) 
    16021709{ 
    1603     debug( "timed out\n" ); 
    16041710    signal( SIGALRM, SIG_IGN ); 
    16051711    alarm( 0 ); 
     1712    error( "timed out\n" ); 
     1713    exit(1); 
    16061714} 
    16071715 
     
    16681776    struct sockaddr_in saddr; 
    16691777 
    1670     if ( relay_method == METHOD_DIRECT ) { 
    1671         host = dest_host; 
    1672         port = dest_port; 
    1673     } else if ((local_resolve (dest_host, &saddr) >= 0)&& 
    1674                (is_direct_address(&saddr))) { 
    1675         debug("%s is connected directly\n", dest_host); 
    1676         relay_method = METHOD_DIRECT; 
    1677         host = dest_host; 
    1678         port = dest_port; 
    1679     } else { 
    1680         host = relay_host; 
    1681         port = relay_port; 
    1682     } 
    1683  
     1778    /* resolve address of proxy or direct target */ 
    16841779    if (local_resolve (host, &saddr) < 0) { 
    16851780        error("can't resolve hostname: %s\n", host); 
     
    27912886#endif /* not _WIN32 */ 
    27922887 
     2888    if (check_direct(dest_host)) 
     2889        relay_method = METHOD_DIRECT; 
    27932890    /* make connection */ 
    27942891    if ( relay_method == METHOD_DIRECT ) { 
login