]> git.saurik.com Git - apple/network_cmds.git/blobdiff - alias/alias_db.c
network_cmds-307.tar.gz
[apple/network_cmds.git] / alias / alias_db.c
index e67705b01091fbe9e15fab575114698dda6a8ce6..f6088dd6009dd63aaa64032af4f3cc4b40dd2b88 100644 (file)
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
+#include <syslog.h>
 
 #include <sys/queue.h>
 #include <sys/socket.h>
 #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; i<LINK_TABLE_OUT_SIZE; i++)
+               {
+                       link = LIST_FIRST(&linkTableOut[i]);
+                       while (link != NULL)
+                       {
+                               struct alias_link *link_next;
+                               char src_str[32], dst_str[32], alias_str[32];
+       
+                               snprintf(src_str, sizeof(src_str), "%s:%u",
+                                       inet_ntoa(link->src_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; i<LINK_TABLE_OUT_SIZE; i++)
+       {
+               link = LIST_FIRST(&linkTableOut[i]);
+               while (link != NULL)
+               {
+                       struct alias_link *link_next;
+                       char src_str[32], dst_str[32], alias_str[32];
+
+                       snprintf(src_str, sizeof(src_str), "%s:%u",
+                               inet_ntoa(link->src_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;
+               }
+       }
+       
+}