X-Git-Url: https://git.saurik.com/apple/network_cmds.git/blobdiff_plain/7ba0088d6898d7fd2873f736f1f556673a8be855..e3d845fab845fed21af97bbae9af95934685d1e9:/alias/alias_db.c diff --git a/alias/alias_db.c b/alias/alias_db.c index e67705b..f6088dd 100644 --- a/alias/alias_db.c +++ b/alias/alias_db.c @@ -169,6 +169,7 @@ #include #include #include +#include #include #include @@ -231,6 +232,9 @@ #endif +static int iChatAVHack = 1; + + /* Dummy port number codes used for FindLinkIn/Out() and AddLink(). These constants can be anything except zero, which indicates an unknown port number. */ @@ -332,6 +336,7 @@ struct alias_link /* Main data structure */ #define LINK_PARTIALLY_SPECIFIED 0x03 /* logical-or of first two bits */ #define LINK_UNFIREWALLED 0x08 #define LINK_LAST_LINE_CRLF_TERMED 0x10 +#define LINK_CONE 0x20 int timestamp; /* Time link was last accessed */ int expire_time; /* Expire time for link */ @@ -592,6 +597,7 @@ FindLinkIn(struct in_addr, struct in_addr, u_short, u_short, int, int); #define GET_NEW_PORT_MAX_ATTEMPTS 20 #define GET_ALIAS_PORT -1 +#define GET_ALIAS_EPHEMERAL_PORT -2 #define GET_ALIAS_ID GET_ALIAS_PORT #define FIND_EVEN_ALIAS_BASE 1 @@ -601,6 +607,45 @@ FindLinkIn(struct in_addr, struct in_addr, u_short, u_short, int, int); another link concurrently. This is because GetNewPort() looks for unused triplets: (dest addr, dest port, alias port). */ +static int +GetEphemeralPort(struct alias_link *link) +{ + int i; + + /* Port number search */ + for (i=0; i < GET_NEW_PORT_MAX_ATTEMPTS; i++) + { + struct sockaddr_in sock_addr; + socklen_t salen; + u_short port_net; + struct alias_link *search_result; + + if (GetSocket(0, &link->sockfd, link->link_type) == 0) + return -1; + salen = sizeof(struct sockaddr_in); + if (getsockname(link->sockfd, (struct sockaddr *)&sock_addr, &salen) == -1) + return -1; + port_net = sock_addr.sin_port; + + search_result = FindLinkIn(link->dst_addr, link->alias_addr, + link->dst_port, port_net, + link->link_type, 0); + + if (search_result == NULL) { + link->alias_port = port_net; + return(0); + } + close(link->sockfd); + link->sockfd = -1; + } + #ifdef DEBUG + fprintf(stderr, "PacketAlias/GetEphemeralPort(): "); + fprintf(stderr, "could not find free port\n"); + #endif + + return(-1); +} + static int GetNewPort(struct alias_link *link, int alias_port_param) { @@ -609,6 +654,9 @@ GetNewPort(struct alias_link *link, int alias_port_param) u_short port_sys; u_short port_net; + if (alias_port_param == GET_ALIAS_EPHEMERAL_PORT) + return GetEphemeralPort(link); + /* Description of alias_port_param for GetNewPort(). When this parameter is zero or positive, it precisely specifies @@ -618,7 +666,6 @@ GetNewPort(struct alias_link *link, int alias_port_param) When this parameter is GET_ALIAS_PORT, it indicates to get a randomly selected port number. */ - if (alias_port_param == GET_ALIAS_PORT) { /* @@ -704,7 +751,6 @@ GetNewPort(struct alias_link *link, int alias_port_param) port_sys += ALIAS_PORT_BASE; port_net = htons(port_sys); } - #ifdef DEBUG fprintf(stderr, "PacketAlias/GetnewPort(): "); fprintf(stderr, "could not find free port\n"); @@ -998,14 +1044,41 @@ DeleteLink(struct alias_link *link) break; } +#ifdef DEBUG + if ((packetAliasMode & PKT_ALIAS_LOG) != 0 && + !IN_MULTICAST(link->src_addr.s_addr) && + !IN_MULTICAST(link->dst_addr.s_addr)) + { + char src[16]; + char dst[16]; + char alias[16]; + char *proto; + switch(link->link_type) + { + case LINK_TCP: + proto = " [TCP]"; + break; + case LINK_UDP: + proto = " [UDP]"; + break; + default: + proto = ""; + } + fprintf(monitorFile, "Deleted%s %s:%d<->%s:%d to %s:%d<->%s:%d\n", + proto, + inet_ntop(AF_INET, &link->src_addr, src, sizeof(src)), link->src_port, + inet_ntop(AF_INET, &link->dst_addr, dst, sizeof(dst)), link->dst_port, + inet_ntop(AF_INET, &link->alias_addr, alias, sizeof(alias)), link->alias_port, + dst, link->dst_port); + fflush(monitorFile); + } +#else + if (packetAliasMode & PKT_ALIAS_LOG) + ShowAliasStats(); +#endif + /* Free memory */ free(link); - -/* Write statistics, if logging enabled */ - if (packetAliasMode & PKT_ALIAS_LOG) - { - ShowAliasStats(); - } } @@ -1045,7 +1118,10 @@ AddLink(struct in_addr src_addr, link->expire_time = ICMP_EXPIRE_TIME; break; case LINK_UDP: - link->expire_time = UDP_EXPIRE_TIME; + if (dst_addr.s_addr == 0 && dst_port == 0) + link->expire_time = UDP_EXPIRE_TIME * 5; + else + link->expire_time = UDP_EXPIRE_TIME; break; case LINK_TCP: link->expire_time = TCP_EXPIRE_INITIAL; @@ -1078,7 +1154,6 @@ AddLink(struct in_addr src_addr, free(link); return(NULL); } - /* Link-type dependent initialization */ switch(link_type) { @@ -1149,10 +1224,37 @@ AddLink(struct in_addr src_addr, #endif } - if (packetAliasMode & PKT_ALIAS_LOG) +#ifdef DEBUG + if ((packetAliasMode & PKT_ALIAS_LOG) != 0 && + !IN_MULTICAST(link->src_addr.s_addr) && + !IN_MULTICAST(link->dst_addr.s_addr)) { - ShowAliasStats(); - } + char src[16]; + char dst[16]; + char alias[16]; + char *proto; + switch(link->link_type) + { + case LINK_TCP: + proto = " [TCP]"; + break; + case LINK_UDP: + proto = " [UDP]"; + break; + default: + proto = ""; + } + fprintf(monitorFile, "Added %s %s:%d<->%s:%d to %s:%d<->%s:%d\n", + proto, + inet_ntop(AF_INET, &link->src_addr, src, sizeof(src)), link->src_port, + inet_ntop(AF_INET, &link->dst_addr, dst, sizeof(dst)), link->dst_port, + inet_ntop(AF_INET, &link->alias_addr, alias, sizeof(alias)), link->alias_port, + dst, link->dst_port); + } +#else + if (packetAliasMode & PKT_ALIAS_LOG) + ShowAliasStats(); +#endif return(link); } @@ -1179,7 +1281,8 @@ ReLink(struct alias_link *old_link, PunchFWHole(new_link); } #endif - DeleteLink(old_link); + if ((old_link->flags & LINK_CONE) == 0) + DeleteLink(old_link); return new_link; } @@ -1668,11 +1771,25 @@ FindUdpTcpOut(struct in_addr src_addr, if (link == NULL && create) { struct in_addr alias_addr; + struct in_addr dst_addr2 = dst_addr; + u_short dst_port2 = dst_port; alias_addr = FindAliasAddress(src_addr); - link = AddLink(src_addr, dst_addr, alias_addr, - src_port, dst_port, GET_ALIAS_PORT, + + if (iChatAVHack && link_type == LINK_UDP && dst_port == htons(5678)) { + dst_addr2.s_addr = 0; + dst_port2 = 0; + } + link = AddLink(src_addr, dst_addr2, alias_addr, + src_port, dst_port2, GET_ALIAS_PORT, link_type); + if (link != NULL && + (link->flags & (LINK_UNKNOWN_DEST_ADDR | LINK_UNKNOWN_DEST_PORT)) != 0) + { + link->flags |= LINK_CONE; + link = ReLink(link, link->src_addr, dst_addr, link->alias_addr, + link->src_port, dst_port, link->alias_port, link_type); + } } return(link); @@ -1863,6 +1980,115 @@ FindAliasAddress(struct in_addr original_addr) } } +/* FindAliasPortOut */ +/* external routine for NatPortMap */ +/* return alias port for the src_addr,dst_addr,src_port and proto */ +/* if one doesn't existed, create a mapping with providing pub_port if it's not 0 */ +/* delete mapping if addmapping is not true */ +int +FindAliasPortOut(struct in_addr src_addr, struct in_addr dst_addr, u_short src_port, u_short pub_port, u_char proto, int lifetime, char addmapping) +{ + u_int i; + struct alias_link *link; + int link_type; + + switch (proto) + { + case IPPROTO_UDP: + link_type = LINK_UDP; + break; + case IPPROTO_TCP: + link_type = LINK_TCP; + break; + default: + return 0; + break; + } + +#ifdef DEBUG + { + int icount = 0; + + printf("FindAliasPortOut:: srcaddr= %s:%u, ", + inet_ntoa(src_addr), ntohs(src_port)); + printf("dstadd= %s:%u link_type= %d, lifetime= %d\n", + inet_ntoa(dst_addr), ntohs(pub_port), link_type, lifetime); + + for (i=0; isrc_addr), ntohs(link->src_port)); + snprintf(dst_str, sizeof(dst_str), "%s:%u", + inet_ntoa(link->dst_addr), ntohs(link->dst_port)); + snprintf(alias_str, sizeof(alias_str), "%s:%u", + inet_ntoa(link->alias_addr), ntohs(link->alias_port)); + + printf(" linkTableOut[%d:%d] src= %s dst= %s alias= %s flags= 0x%x linktype= %d ts= %d exp= %d fd= %d", + i, icount, src_str, dst_str, alias_str, + link->flags, link->link_type, link->timestamp, link->expire_time, link->sockfd); + + link_next = LIST_NEXT(link, list_out); + icount++; + link = link_next; + } + } + + } +#endif + + i = StartPointOut(src_addr, dst_addr, src_port, 0, link_type); +#ifdef DEBUG + printf("PORTMAP::StartPointOut returns %d\n", i); +#endif + LIST_FOREACH(link, &linkTableOut[i], list_out) + { + if (link->src_addr.s_addr == src_addr.s_addr && + link->dst_addr.s_addr == dst_addr.s_addr && + link->src_port == src_port && link->link_type == link_type) + break; + } + + if ( link == NULL && addmapping) + { + struct in_addr alias_addr; +#ifdef DEBUG + printf("PORTMAP:: cannot find mapping, adding mapping private port =%d, public port = %d\n", + src_port, pub_port); +#endif + /* address/port in not in list, create new mapping */ + + alias_addr = FindAliasAddress(src_addr); + /* create new mapping */ + link = AddLink(src_addr, dst_addr, alias_addr, + src_port, 0, GET_ALIAS_EPHEMERAL_PORT, + link_type); + if ( link != NULL ) { + /* link was create, set new lifetime */ + SetExpire(link, lifetime); + /* Prevent link deletion when incoming connection arrive */ + link->flags |= LINK_CONE; + } + } + if ( link ) + { + if ( addmapping ) + return( GetAliasPort(link)); + else + { + SetExpire(link, 0); /* delete mapping */ + return 0; + } + } + + return -1; +} + /* External routines for getting or changing link data (external to alias_db.c, but internal to alias*.c) @@ -2831,3 +3057,36 @@ PacketAliasSetFWBase(unsigned int base, unsigned int num) { fireWallNumNums = num; #endif } + +void +DumpInfo(void) +{ + int i, icount = 0; + struct alias_link *link; + + for (i=0; isrc_addr), ntohs(link->src_port)); + snprintf(dst_str, sizeof(dst_str), "%s:%u", + inet_ntoa(link->dst_addr), ntohs(link->dst_port)); + snprintf(alias_str, sizeof(alias_str), "%s:%u", + inet_ntoa(link->alias_addr), ntohs(link->alias_port)); + + syslog(LOG_ERR, " linkTableOut[%d:%d] src= %s dst= %s alias= %s flags= 0x%x linktype= %d ts= %d exp= %d fd= %d", + i, icount, src_str, dst_str, alias_str, + link->flags, link->link_type, link->timestamp, link->expire_time, link->sockfd); + + link_next = LIST_NEXT(link, list_out); + icount++; + link = link_next; + } + } + +}