diff -Nur natd-libalias-orig/README natd-libalias/README --- natd-libalias-orig/README Fri Apr 25 02:50:12 2003 +++ natd-libalias/README Thu Jan 1 01:00:00 1970 @@ -1,50 +0,0 @@ -# $FreeBSD: src/sbin/natd/README,v 1.1.4.1 2000/04/02 20:24:48 brian Exp $ - - A Network Address Translation Daemon for FreeBSD - - -1. WHAT IS NATD ? - - This is a simple daemon based on FreeBSD divert sockets - which performs network address translation (or masquerading) - for IP packets (see related RFCs 1631 and 1918). - It is based on packet aliasing package (see README.alias) - written by Charles Mott (cmott@scientech.com). - - This package works with any network interface (doesn't have - to be ppp). I run it on a computer having two ethernet cards, - one connected to internet and the other one to local network. - -2. GETTING IT RUNNING - - 1) Get FreeBSD 2.2 - I think the divert sockets are - not available on earlier versions, - - 2) Compile this software by executing "make". - - 3) Install the software by executing "make install". - - 4) See man natd for further instructions. - -3. FTP SITES FOR NATD - - This package is available at ftp://ftp.suutari.iki.fi/pub/natd. - -4. AUTHORS - - This program is the result of the efforts of many people - at different times: - - Archie Cobbs Divert sockets - Charles Mott Packet aliasing engine - Eivind Eklund Packet aliasing engine - Ari Suutari Natd - Brian Somers Manual page, glue and - bunch of good ideas. - - Happy Networking - comments and fixes are welcome! - - Ari S. (suutari@iki.fi) - - - diff -Nur natd-libalias-orig/alias.c natd-libalias/alias.c --- natd-libalias-orig/alias.c Fri Apr 25 02:50:28 2003 +++ natd-libalias/alias.c Fri Apr 25 01:27:17 2003 @@ -911,7 +911,7 @@ u_short proxy_port; int accumulate; u_short *sptr; - + /* Special processing for IP encoding protocols */ if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER) @@ -994,6 +994,7 @@ } ADJUST_CHECKSUM(accumulate, pip->ip_sum); + //DebugLink(link); /* Monitor TCP connection state */ TcpMonitorIn(pip, link); diff -Nur natd-libalias-orig/alias.h natd-libalias/alias.h --- natd-libalias-orig/alias.h Fri Apr 25 02:50:28 2003 +++ natd-libalias/alias.h Sat Apr 26 22:14:21 2003 @@ -48,7 +48,8 @@ unsigned int PacketAliasSetMode(unsigned int _flags, unsigned int _mask); void PacketAliasUninit(void); - +void ServersStats(void); + /* Packet Handling functions. */ int PacketAliasIn(char *_ptr, int _maxpacketsize); int PacketAliasOut(char *_ptr, int _maxpacketsize); @@ -59,22 +60,23 @@ /* * An anonymous structure, a pointer to which is returned from * PacketAliasRedirectAddr(), PacketAliasRedirectPort() or - * PacketAliasRedirectProto(), passed to PacketAliasAddServer(), + * PacketAliasRedirectProto(), passed to PwacketAliasAddServer(), * and freed by PacketAliasRedirectDelete(). */ struct alias_link; int PacketAliasAddServer(struct alias_link *_link, - struct in_addr _addr, unsigned short _port); + struct in_addr _addr, unsigned short _port,int _weight); struct alias_link * PacketAliasRedirectAddr(struct in_addr _src_addr, - struct in_addr _alias_addr); + struct in_addr _alias_addr, int _weight); void PacketAliasRedirectDelete(struct alias_link *_link); struct alias_link * PacketAliasRedirectPort(struct in_addr _src_addr, unsigned short _src_port, struct in_addr _dst_addr, unsigned short _dst_port, struct in_addr _alias_addr, - unsigned short _alias_port, unsigned char _proto); + unsigned short _alias_port, unsigned char _proto, + int _sched_type); struct alias_link * PacketAliasRedirectProto(struct in_addr _src_addr, struct in_addr _dst_addr, struct in_addr _alias_addr, @@ -177,6 +179,15 @@ #define PKT_ALIAS_UNRESOLVED_FRAGMENT 3 #define PKT_ALIAS_FOUND_HEADER_FRAGMENT 4 +void CleanupRedirectList(void); + +#define SCHED_ROUND_ROBIN 0 +#define SCHED_SEQ_WEIGHTED_ROUND_ROBIN 1 +#define SCHED_WEIGHTED_ROUND_ROBIN 2 + +void DebugLink(struct alias_link *_link); + #endif /* !_ALIAS_H_ */ /* lint -restore */ + diff -Nur natd-libalias-orig/alias_db.c natd-libalias/alias_db.c --- natd-libalias-orig/alias_db.c Fri Apr 25 02:50:28 2003 +++ natd-libalias/alias_db.c Sat Apr 26 23:16:10 2003 @@ -166,19 +166,20 @@ #include "alias_local.h" - /* Constants (note: constants are also defined near relevant functions or structs) */ /* Sizes of input and output link tables */ -#define LINK_TABLE_OUT_SIZE 101 -#define LINK_TABLE_IN_SIZE 4001 +/* Sizes of input and output link tables */ +#define LINK_TABLE_OUT_SIZE 15979 +#define LINK_TABLE_IN_SIZE 15979 +#define LINK_TABLE_REDIR_IN_SIZE 127 /* Parameters used for cleanup of expired links */ #define ALIAS_CLEANUP_INTERVAL_SECS 60 -#define ALIAS_CLEANUP_MAX_SPOKES 30 +#define ALIAS_CLEANUP_MAX_SPOKES 10 /* Timeouts (in seconds) for different link types */ #define ICMP_EXPIRE_TIME 60 @@ -197,7 +198,7 @@ /* When the link has been used and closed on one side - the other side is allowed to still send data */ #ifndef TCP_EXPIRE_SINGLEDEAD -# define TCP_EXPIRE_SINGLEDEAD 90 +# define TCP_EXPIRE_SINGLEDEAD 30 #endif /* When the link isn't yet up */ @@ -277,9 +278,17 @@ { struct in_addr addr; u_short port; + int maxconns; + int activeconns; + int inactiveconns; struct server *next; + int nb_conns; + int weight; + int current; + int numero; }; + struct alias_link /* Main data structure */ { struct in_addr src_addr; /* Address and port information */ @@ -290,6 +299,7 @@ u_short dst_port; u_short alias_port; u_short proxy_port; + int nb_conns; struct server *server; int link_type; /* Type of link: TCP, UDP, ICMP, proto, frag */ @@ -320,18 +330,17 @@ LIST_ENTRY(alias_link) list_out; /* Linked list of pointers for */ LIST_ENTRY(alias_link) list_in; /* input and output lookup tables */ - + LIST_ENTRY(alias_link) list_redir_in; union /* Auxiliary data */ { char *frag_ptr; struct in_addr frag_addr; struct tcp_dat *tcp; } data; + int sched_type; }; - - - +int max_weight = 0; /* Global Variables @@ -359,6 +368,10 @@ linkTableIn[LINK_TABLE_IN_SIZE]; /* into input and output lookup */ /* tables. */ +static LIST_HEAD(, alias_link) /* link record is doubly indexed */ +linkTableRedirIn[LINK_TABLE_REDIR_IN_SIZE]; /* into input and output lookup */ + /* tables. */ + static int icmpLinkCount; /* Link statistics */ static int udpLinkCount; static int tcpLinkCount; @@ -389,6 +402,8 @@ /* link has been created after a */ /* call to PacketAliasIn/Out(). */ +char *GetSchedName(int); +char *GetProtoName(int); #ifndef NO_FW_PUNCH static int fireWallFD = -1; /* File descriptor to be able to */ /* control firewall. Opened by */ @@ -410,6 +425,7 @@ incoming packets StartPointOut() -- link table initial search point for outgoing packets + StartPointRedirIn() -- Doc to Add Miscellaneous: SeqDiff() -- difference between two TCP sequences @@ -420,6 +436,8 @@ /* Local prototypes */ static u_int StartPointIn(struct in_addr, u_short, int); +static u_int StartPointRedirIn(struct in_addr, u_short, int); + static u_int StartPointOut(struct in_addr, struct in_addr, u_short, u_short, int); @@ -439,17 +457,29 @@ static void UninitPacketAliasLog(void); static u_int -StartPointIn(struct in_addr alias_addr, - u_short alias_port, +StartPointIn(struct in_addr dst_addr, + u_short dst_port, int link_type) { u_int n; + n = dst_addr.s_addr; + if (link_type != LINK_PPTP) + n += dst_port; + n += link_type; + return(n % LINK_TABLE_IN_SIZE); +} +static u_int +StartPointRedirIn(struct in_addr alias_addr, + u_short alias_port, + int link_type) +{ + u_int n; n = alias_addr.s_addr; if (link_type != LINK_PPTP) - n += alias_port; + n += alias_port; n += link_type; - return(n % LINK_TABLE_IN_SIZE); + return(n % LINK_TABLE_REDIR_IN_SIZE); } @@ -466,7 +496,6 @@ n += dst_port; } n += link_type; - return(n % LINK_TABLE_OUT_SIZE); } @@ -552,7 +581,7 @@ static struct alias_link * AddLink(struct in_addr, struct in_addr, struct in_addr, - u_short, u_short, int, int); + u_short, u_short, int, int, int,int); static struct alias_link * ReLink(struct alias_link *, @@ -565,6 +594,9 @@ static struct alias_link * FindLinkIn(struct in_addr, struct in_addr, u_short, u_short, int, int); +static struct alias_link * +FindLinkRedirIn(struct in_addr, struct in_addr, u_short, u_short, int, int); + #define ALIAS_PORT_BASE 0x08000 #define ALIAS_PORT_MASK 0x07fff @@ -863,6 +895,75 @@ cleanupIndex =0; } +void +CleanupRedirectList(void) +{ + struct alias_link *link; + int i, icount; + deleteAllLinks = 1; + icount = 0; + for (i=0; ialias_addr), + ntohs(link_tmp->alias_port), + GetProtoName(link_tmp->link_type), + link_tmp->nb_conns); + if (link->server != NULL) { + struct server *head; + fprintf(StatFile, " Scheduling Type: %s\n",GetSchedName(link_tmp->sched_type)); + head = link_tmp->server->next; + do { + fprintf(StatFile, "\tIP Address: %s\n",inet_ntoa(link_tmp->server->addr)); + fprintf(StatFile, "\tport: %d\n",ntohs(link_tmp->server->port)); + fprintf(StatFile, "\tConnexions: %d\n", link_tmp->server->nb_conns); + fprintf(StatFile, "\tWeight: %d\n\n",link_tmp->server->weight); + link_tmp->server = link_tmp->server->next; + } while (head != link_tmp->server->next); + } else { + fprintf(StatFile, "\tIP Address: %s\n",inet_ntoa(link_tmp->src_addr)); + if (ntohs(link_tmp->alias_port) != 0) + fprintf(StatFile, "\tport: %d\n\n",ntohs(link_tmp->src_port)); + else + fprintf(StatFile, "\tport: Protocol or address redirect.\n\n"); + } + link = link_next; + } + } + fclose(StatFile); +} + static void IncrementalCleanup(void) @@ -934,12 +1035,16 @@ } while ((curr = next) != head); } + //LIST_REMOVE(link, list_redir_in); + /* Adjust output table pointers */ LIST_REMOVE(link, list_out); - -/* Adjust input table pointers */ +if ( link->flags & LINK_PERMANENT ) + LIST_REMOVE(link, list_redir_in); +else LIST_REMOVE(link, list_in); + /* Close socket, if one has been allocated */ if (link->sockfd != -1) { @@ -996,7 +1101,9 @@ u_short src_port, u_short dst_port, int alias_port_param, /* if less than zero, alias */ - int link_type) /* port will be automatically */ + int link_type, + int isredir, + int sched_type) /* port will be automatically */ { /* chosen. If greater than */ u_int start_point; /* zero, equal to alias port */ struct alias_link *link; @@ -1012,11 +1119,16 @@ link->src_port = src_port; link->dst_port = dst_port; link->proxy_port = 0; + link->nb_conns = 0; link->server = NULL; link->link_type = link_type; link->sockfd = -1; link->flags = 0; link->timestamp = timeStamp; + if ( isredir == 1 ) + link->sched_type = sched_type; + else + link->sched_type = 0; /* Expiration time */ switch (link_type) @@ -1085,6 +1197,7 @@ aux_tcp->ack[i].active = 0; aux_tcp->fwhole = -1; link->data.tcp = aux_tcp; + } else { @@ -1092,6 +1205,7 @@ fprintf(stderr, "PacketAlias/AddLink: "); fprintf(stderr, " cannot allocate auxiliary TCP data\n"); #endif + free(link); return (NULL); } @@ -1118,15 +1232,19 @@ LIST_INSERT_HEAD(&linkTableOut[start_point], link, list_out); /* Set up pointers for input lookup table */ - start_point = StartPointIn(alias_addr, link->alias_port, link_type); - LIST_INSERT_HEAD(&linkTableIn[start_point], link, list_in); - } - else - { + if (isredir == 0) { + start_point = StartPointIn(dst_addr, dst_port, link_type); + LIST_INSERT_HEAD(&linkTableIn[start_point], link, list_in); + } else { + start_point = StartPointRedirIn(alias_addr, link->alias_port, link_type); + LIST_INSERT_HEAD(&linkTableRedirIn[start_point], link, list_redir_in); + } + } else { #ifdef DEBUG fprintf(stderr, "PacketAlias/AddLink(): "); fprintf(stderr, "malloc() call failed.\n"); #endif + } if (packetAliasMode & PKT_ALIAS_LOG) @@ -1151,7 +1269,8 @@ new_link = AddLink(src_addr, dst_addr, alias_addr, src_port, dst_port, alias_port_param, - link_type); + link_type,0,0); + #ifndef NO_FW_PUNCH if (new_link != NULL && old_link->link_type == LINK_TCP && @@ -1177,6 +1296,7 @@ i = StartPointOut(src_addr, dst_addr, src_port, dst_port, link_type); LIST_FOREACH(link, &linkTableOut[i], list_out) { + if (link->src_addr.s_addr == src_addr.s_addr && link->server == NULL && link->dst_addr.s_addr == dst_addr.s_addr @@ -1281,12 +1401,14 @@ flags_in |= LINK_UNKNOWN_DEST_PORT; /* Search loop */ - start_point = StartPointIn(alias_addr, alias_port, link_type); + + start_point = StartPointIn(dst_addr, dst_port, link_type); + start_point = StartPointIn(dst_addr, dst_port, link_type); LIST_FOREACH(link, &linkTableIn[start_point], list_in) { int flags; - flags = flags_in | link->flags; + if (!(flags & LINK_PARTIALLY_SPECIFIED)) { if (link->alias_addr.s_addr == alias_addr.s_addr @@ -1334,8 +1456,7 @@ } } - - + if (link_fully_specified != NULL) { link_fully_specified->timestamp = timeStamp; @@ -1355,16 +1476,18 @@ { struct in_addr src_addr; u_short src_port; - if (link->server != NULL) { /* LSNAT link */ src_addr = link->server->addr; src_port = link->server->port; - link->server = link->server->next; + //link->server = link->server->next; + link = choose_next_server(link); + } else { src_addr = link->src_addr; src_port = link->src_port; } + link = ReLink(link, src_addr, dst_addr, alias_addr, src_port, dst_port, alias_port, @@ -1439,10 +1562,10 @@ { struct in_addr target_addr; - target_addr = FindOriginalAddress(alias_addr); + target_addr = FindOriginalAddress(alias_addr,0,IPPROTO_ICMP); link = AddLink(target_addr, dst_addr, alias_addr, id_alias, NO_DEST_PORT, id_alias, - LINK_ICMP); + LINK_ICMP,0,0); } return (link); @@ -1467,7 +1590,7 @@ alias_addr = FindAliasAddress(src_addr); link = AddLink(src_addr, dst_addr, alias_addr, id, NO_DEST_PORT, GET_ALIAS_ID, - LINK_ICMP); + LINK_ICMP,0,0); } return(link); @@ -1483,13 +1606,13 @@ link = FindLinkIn(dst_addr, alias_addr, NO_DEST_PORT, ip_id, - LINK_FRAGMENT_ID, 0); + LINK_FRAGMENT_ID,0); if (link == NULL) { link = AddLink(nullAddress, dst_addr, alias_addr, NO_SRC_PORT, NO_DEST_PORT, ip_id, - LINK_FRAGMENT_ID); + LINK_FRAGMENT_ID,0,0); } return(link); @@ -1513,7 +1636,7 @@ { return AddLink(nullAddress, dst_addr, nullAddress, NO_SRC_PORT, NO_DEST_PORT, ip_id, - LINK_FRAGMENT_PTR); + LINK_FRAGMENT_PTR,0,0); } @@ -1542,10 +1665,11 @@ { struct in_addr target_addr; - target_addr = FindOriginalAddress(alias_addr); + target_addr = FindOriginalAddress(alias_addr,0,IPPROTO_ICMP); + link = AddLink(target_addr, dst_addr, alias_addr, NO_SRC_PORT, NO_DEST_PORT, 0, - proto); + proto,0,0); } return (link); @@ -1570,7 +1694,7 @@ alias_addr = FindAliasAddress(src_addr); link = AddLink(src_addr, dst_addr, alias_addr, NO_SRC_PORT, NO_DEST_PORT, 0, - proto); + proto,0,0); } return (link); @@ -1579,7 +1703,7 @@ struct alias_link * FindUdpTcpIn(struct in_addr dst_addr, - struct in_addr alias_addr, + struct in_addr alias_addr, u_short dst_port, u_short alias_port, u_char proto, @@ -1587,7 +1711,6 @@ { int link_type; struct alias_link *link; - switch (proto) { case IPPROTO_UDP: @@ -1600,7 +1723,6 @@ return NULL; break; } - link = FindLinkIn(dst_addr, alias_addr, dst_port, alias_port, link_type, create); @@ -1608,11 +1730,10 @@ if (link == NULL && create && !(packetAliasMode & PKT_ALIAS_DENY_INCOMING)) { struct in_addr target_addr; - - target_addr = FindOriginalAddress(alias_addr); + target_addr = FindOriginalAddress(alias_addr,alias_port,link_type); link = AddLink(target_addr, dst_addr, alias_addr, alias_port, dst_port, alias_port, - link_type); + link_type,0,0); } return(link); @@ -1652,7 +1773,7 @@ alias_addr = FindAliasAddress(src_addr); link = AddLink(src_addr, dst_addr, alias_addr, src_port, dst_port, GET_ALIAS_PORT, - link_type); + link_type,0,0); } return(link); @@ -1669,7 +1790,7 @@ link = AddLink(src_addr, dst_addr, alias_addr, src_call_id, 0, GET_ALIAS_PORT, - LINK_PPTP); + LINK_PPTP,0,0); return (link); } @@ -1723,7 +1844,7 @@ u_int i; struct alias_link *link; - i = StartPointIn(alias_addr, 0, LINK_PPTP); + i = StartPointIn(dst_addr, 0, LINK_PPTP); LIST_FOREACH(link, &linkTableIn[i], list_in) if (link->link_type == LINK_PPTP && link->dst_addr.s_addr == dst_addr.s_addr && @@ -1783,44 +1904,13 @@ alias_addr = FindAliasAddress(src_addr); link = AddLink(src_addr, dst_addr, alias_addr, src_port, 0, alias_port, - link_type); + link_type,0,0); } return(link); } -struct in_addr -FindOriginalAddress(struct in_addr alias_addr) -{ - struct alias_link *link; - - link = FindLinkIn(nullAddress, alias_addr, - 0, 0, LINK_ADDR, 0); - if (link == NULL) - { - newDefaultLink = 1; - if (targetAddress.s_addr == INADDR_ANY) - return alias_addr; - else if (targetAddress.s_addr == INADDR_NONE) - return aliasAddress; - else - return targetAddress; - } - else - { - if (link->server != NULL) { /* LSNAT link */ - struct in_addr src_addr; - - src_addr = link->server->addr; - link->server = link->server->next; - return (src_addr); - } else if (link->src_addr.s_addr == INADDR_ANY) - return aliasAddress; - else - return link->src_addr; - } -} struct in_addr @@ -2366,14 +2456,21 @@ /* Redirection from a specific public addr:port to a private addr:port */ +/* scheduling type : + 0 || NULL : Classic Round Robin + 1 : +*/ struct alias_link * PacketAliasRedirectPort(struct in_addr src_addr, u_short src_port, struct in_addr dst_addr, u_short dst_port, struct in_addr alias_addr, u_short alias_port, - u_char proto) + u_char proto, int sched_type) { int link_type; struct alias_link *link; + if (sched_type == NULL) { + sched_type = SCHED_ROUND_ROBIN ; + } switch(proto) { @@ -2390,10 +2487,9 @@ #endif return NULL; } - link = AddLink(src_addr, dst_addr, alias_addr, src_port, dst_port, alias_port, - link_type); + link_type,1,sched_type); if (link != NULL) { @@ -2406,13 +2502,12 @@ "call to AddLink() failed\n"); } #endif - return link; } /* Add server to the pool of servers */ int -PacketAliasAddServer(struct alias_link *link, struct in_addr addr, u_short port) +PacketAliasAddServer(struct alias_link *link, struct in_addr addr, u_short port,int weight) { struct server *server; @@ -2423,7 +2518,9 @@ server->addr = addr; server->port = port; - + server->nb_conns = 0; + server->weight = weight; + server->current=1; head = link->server; if (head == NULL) server->next = server; @@ -2452,7 +2549,7 @@ link = AddLink(src_addr, dst_addr, alias_addr, NO_SRC_PORT, NO_DEST_PORT, 0, - proto); + proto,1,0); if (link != NULL) { @@ -2472,13 +2569,14 @@ /* Static address translation */ struct alias_link * PacketAliasRedirectAddr(struct in_addr src_addr, - struct in_addr alias_addr) + struct in_addr alias_addr, + int sched_type) { struct alias_link *link; link = AddLink(src_addr, nullAddress, alias_addr, 0, 0, 0, - LINK_ADDR); + LINK_ADDR,1,sched_type); if (link != NULL) { @@ -2545,6 +2643,9 @@ LIST_INIT(&linkTableOut[i]); for (i=0; isched_type) { + case SCHED_ROUND_ROBIN: + _link->server->nb_conns++; + _link->server = _link->server->next; + _link->nb_conns++; + break; + + case SCHED_SEQ_WEIGHTED_ROUND_ROBIN: + if (_link->server->weight <= _link->server->current) { + _link->server->current=1; + _link->server->nb_conns++; + _link->server = _link->server->next; + } else { + _link->server->current++; + _link->server->nb_conns++; + } + _link->nb_conns++; + break; + + case SCHED_WEIGHTED_ROUND_ROBIN: + _link->server = _link->server->next; + if (_link->server->weight > max_weight) + max_weight = _link->server->weight; + + do { + if (max_weight >= _link->server->current ) { + if (_link->server->weight >= _link->server->current) { + _link->server->nb_conns++; + _link->server->current++; + breaking=1; + } else { + _link->server->current++; + _link->server = _link->server->next; + } + } else { + _link->server->current=1; + _link->server->nb_conns++; + _link->server->current++; + breaking=1; + } + } while (breaking != 1); + _link->nb_conns++; + break; + + default: + _link->server = _link->server->next; + _link->server->nb_conns++; + break; + } + return (_link); +} + +void +DebugLink(struct alias_link *_link) { + fprintf(stderr,"Debug Du Link !!!\n"); + fprintf(stderr,"dest %s : \n", inet_ntoa(_link->dst_addr)); + fprintf(stderr,"source %s : \n", inet_ntoa(_link->src_addr)); + fprintf(stderr,"alias %s : \n", inet_ntoa(_link->alias_addr)); +} + +static struct alias_link * +_FindLinkRedirIn(struct in_addr dst_addr, + struct in_addr alias_addr, + u_short dst_port, + u_short alias_port, + int link_type, + int replace_partial_links) +{ + u_int start_point; + struct alias_link *link; + +/* Search loop */ + + start_point = StartPointRedirIn(alias_addr, alias_port, link_type); + LIST_FOREACH(link, &linkTableRedirIn[start_point], list_redir_in) + { + if (link->alias_addr.s_addr == alias_addr.s_addr + && link->alias_port == alias_port + && link->link_type == link_type) + { + break; + } + } + return (link); +} + +static struct alias_link * +FindLinkRedirIn(struct in_addr dst_addr, + struct in_addr alias_addr, + u_short dst_port, + u_short alias_port, + int link_type, + int replace_partial_links) +{ + struct alias_link *link; + link = _FindLinkRedirIn(dst_addr, alias_addr, dst_port, alias_port, + link_type, replace_partial_links); + + if (link == NULL) + { + /* The following allows permanent links to be + specified as using the default aliasing address + (i.e. device interface address) without knowing + in advance what that address is. */ + if (aliasAddress.s_addr != 0 && + alias_addr.s_addr == aliasAddress.s_addr) + { + link = _FindLinkRedirIn(dst_addr, nullAddress, dst_port, alias_port, + link_type, replace_partial_links); + } + } + + return(link); +} + +struct in_addr +FindOriginalAddress(struct in_addr alias_addr, u_short alias_port, int link_type) +{ + struct alias_link *link = NULL ; + +#warning "FIX ME" + if (link_type != IPPROTO_ICMP) { + /* Looking For RedirectPort */ + if ((link = FindLinkRedirIn(nullAddress, alias_addr,0, alias_port,link_type, 0)) == NULL) + if ((link = FindLinkRedirIn(nullAddress, alias_addr, 0, 0 ,LINK_ADDR, 0)) == NULL ) + link = FindLinkRedirIn(nullAddress, alias_addr, + 0,0,link_type,0); + } + + if (link == NULL) + link = FindLinkIn(nullAddress, alias_addr, + 0, 0, LINK_ADDR, 0); + + + if (link == NULL) + { + newDefaultLink = 1; + if (targetAddress.s_addr == INADDR_ANY) + return alias_addr; + else if (targetAddress.s_addr == INADDR_NONE) + return aliasAddress; + else + return targetAddress; + } + else + { + if (link->server != NULL) { /* LSNAT link */ + struct in_addr src_addr; + + src_addr = link->server->addr; + //link->server = link->server->next; + link = choose_next_server(link); + return (src_addr); + } else if (link->src_addr.s_addr == INADDR_ANY) + return aliasAddress; + else + return link->src_addr; + + } +} + +char * +GetSchedName (int sched_type) { + + char *SchedName = "none"; + switch (sched_type) { + case SCHED_ROUND_ROBIN: + SchedName="Rond Roubin"; + break; + case SCHED_SEQ_WEIGHTED_ROUND_ROBIN: + SchedName="Sequential Weighted Round Robin"; + break; + case SCHED_WEIGHTED_ROUND_ROBIN: + SchedName="Weighted Round Robin"; + break; + } + return(SchedName); +} + +#define LINK_ICMP IPPROTO_ICMP +#define LINK_UDP IPPROTO_UDP +#define LINK_TCP IPPROTO_TCP +#define LINK_FRAGMENT_ID (IPPROTO_MAX + 1) +#define LINK_FRAGMENT_PTR (IPPROTO_MAX + 2) +#define LINK_ADDR (IPPROTO_MAX + 3) +#define LINK_PPTP (IPPROTO_MAX + 4) + +char * +GetProtoName (int proto) { + + char *ProtoName = "unknown"; + switch (proto) { + case LINK_UDP: + ProtoName="udp"; + break; + case LINK_TCP: + ProtoName="tcp"; + break; + case IPPROTO_MAX: + ProtoName="redirect"; + break; + } + return(ProtoName); } diff -Nur natd-libalias-orig/alias_local.h natd-libalias/alias_local.h --- natd-libalias-orig/alias_local.h Fri Apr 25 02:50:28 2003 +++ natd-libalias/alias_local.h Fri Apr 25 01:27:17 2003 @@ -131,9 +131,11 @@ FindRtspOut(struct in_addr _src_addr, struct in_addr _dst_addr, u_short _src_port, u_short _alias_port, u_char _proto); struct in_addr - FindOriginalAddress(struct in_addr _alias_addr); + FindOriginalAddress(struct in_addr _alias_addr,ushort _alias_port, int _link_type); struct in_addr FindAliasAddress(struct in_addr _original_addr); +struct alias_link * + choose_next_server (struct alias_link *_link); /* External data access/modification */ int FindNewPortGroup(struct in_addr _dst_addr, struct in_addr _alias_addr, diff -Nur natd-libalias-orig/libalias.3 natd-libalias/libalias.3 --- natd-libalias-orig/libalias.3 Fri Apr 25 02:50:28 2003 +++ natd-libalias/libalias.3 Thu Jan 1 01:00:00 1970 @@ -1,981 +0,0 @@ -.\"- -.\" Copyright (c) 2001 Charles Mott -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD: src/lib/libalias/libalias.3,v 1.23.2.11 2001/12/17 10:08:22 ru Exp $ -.\" -.Dd April 13, 2000 -.Dt LIBALIAS 3 -.Os -.Sh NAME -.Nm libalias -.Nd packet aliasing library for masquerading and network address translation -.Sh SYNOPSIS -.In sys/types.h -.In netinet/in.h -.In alias.h -.Pp -Function prototypes are given in the main body of the text. -.Sh DESCRIPTION -The -.Nm -library is a collection of functions for aliasing and de-aliasing of IP -packets, intended for masquerading and network address translation (NAT). -.Sh INTRODUCTION -This library is a moderately portable set of functions designed to assist -in the process of IP masquerading and network address translation. -Outgoing packets from a local network with unregistered IP addresses can -be aliased to appear as if they came from an accessible IP address. -Incoming packets are then de-aliased so that they are sent to the correct -machine on the local network. -.Pp -A certain amount of flexibility is built into the packet aliasing engine. -In the simplest mode of operation, a many-to-one address mapping takes -place between local network and the packet aliasing host. -This is known as IP masquerading. -In addition, one-to-one mappings between local and public addresses can -also be implemented, which is known as static NAT. -In between these extremes, different groups of private addresses can be -linked to different public addresses, comprising several distinct -many-to-one mappings. -Also, a given public address and port can be statically redirected to a -private address/port. -.Pp -The packet aliasing engine was designed to operate in user space outside -of the kernel, without any access to private kernel data structure, but -the source code can also be ported to a kernel environment. -.Sh INITIALIZATION AND CONTROL -Two special functions, -.Fn PacketAliasInit -and -.Fn PacketAliasSetAddress , -must always be called before any packet handling may be performed. -In addition, the operating mode of the packet aliasing engine can be -customized by calling -.Fn PacketAliasSetMode . -.Pp -.Ft void -.Fn PacketAliasInit void -.Bd -ragged -offset indent -This function has no arguments or return value and is used to initialize -internal data structures. -The following mode bits are always set after calling -.Fn PacketAliasInit . -See the description of -.Fn PacketAliasSetMode -below for the meaning of these mode bits. -.Pp -.Bl -item -offset indent -compact -.It -.Dv PKT_ALIAS_SAME_PORTS -.It -.Dv PKT_ALIAS_USE_SOCKETS -.It -.Dv PKT_ALIAS_RESET_ON_ADDR_CHANGE -.El -.Pp -This function will always return the packet aliasing engine to the same -initial state. -.Fn PacketAliasSetAddress -must be called afterwards, and any desired changes from the default mode -bits listed above require a call to -.Fn PacketAliasSetMode . -.Pp -It is mandatory that this function be called at the beginning of a program -prior to any packet handling. -.Ed -.Pp -.Ft void -.Fn PacketAliasUninit void -.Bd -ragged -offset indent -This function has no arguments or return value and is used to clear any -resources attached to internal data structures. -.Pp -This functions should be called when a program stops using the aliasing -engine; it does, amongst other things, clear out any firewall holes. -To provide backwards compatibility and extra security, it is added to -the -.Xr atexit 3 -chain by -.Fn PacketAliasInit . -Calling it multiple times is harmless. -.Ed -.Pp -.Ft void -.Fn PacketAliasSetAddress "struct in_addr addr" -.Bd -ragged -offset indent -This function sets the source address to which outgoing packets from the -local area network are aliased. -All outgoing packets are re-mapped to this address unless overridden by a -static address mapping established by -.Fn PacketAliasRedirectAddr . -.Pp -If the -.Dv PKT_ALIAS_RESET_ON_ADDR_CHANGE -mode bit is set (the default mode of operation), then the internal aliasing -link tables will be reset any time the aliasing address changes. -This is useful for interfaces such as -.Xr ppp 8 , -where the IP -address may or may not change on successive dial-up attempts. -.Pp -If the -.Dv PKT_ALIAS_RESET_ON_ADDR_CHANGE -mode bit is set to zero, this function can also be used to dynamically change -the aliasing address on a packet to packet basis (it is a low overhead call). -.Pp -It is mandatory that this function be called prior to any packet handling. -.Ed -.Pp -.Ft unsigned int -.Fn PacketAliasSetMode "unsigned int flags" "unsigned int mask" -.Bd -ragged -offset indent -This function sets or clears mode bits -according to the value of -.Fa flags . -Only bits marked in -.Fa mask -are affected. -The following mode bits are defined in -.Aq Pa alias.h : -.Bl -tag -width indent -.It Dv PKT_ALIAS_LOG -Enables logging into -.Pa /var/log/alias.log . -Each time an aliasing link is created or deleted, the log file is appended -with the current number of ICMP, TCP and UDP links. -Mainly useful for debugging when the log file is viewed continuously with -.Xr tail 1 . -.It Dv PKT_ALIAS_DENY_INCOMING -If this mode bit is set, all incoming packets associated with new TCP -connections or new UDP transactions will be marked for being ignored -.Fn ( PacketAliasIn -returns -.Dv PKT_ALIAS_IGNORED -code) -by the calling program. -Response packets to connections or transactions initiated from the packet -aliasing host or local network will be unaffected. -This mode bit is useful for implementing a one-way firewall. -.It Dv PKT_ALIAS_SAME_PORTS -If this mode bit is set, the packet aliasing engine will attempt to leave -the alias port numbers unchanged from the actual local port numbers. -This can be done as long as the quintuple (proto, alias addr, alias port, -remote addr, remote port) is unique. -If a conflict exists, a new aliasing port number is chosen even if this -mode bit is set. -.It Dv PKT_ALIAS_USE_SOCKETS -This bit should be set when the packet aliasing host originates network -traffic as well as forwards it. -When the packet aliasing host is waiting for a connection from an unknown -host address or unknown port number (e.g. an FTP data connection), this -mode bit specifies that a socket be allocated as a place holder to prevent -port conflicts. -Once a connection is established, usually within a minute or so, the socket -is closed. -.It Dv PKT_ALIAS_UNREGISTERED_ONLY -If this mode bit is set, traffic on the local network which does not -originate from unregistered address spaces will be ignored. -Standard Class A, B and C unregistered addresses are: -.Bd -literal -offset indent -10.0.0.0 -> 10.255.255.255 (Class A subnet) -172.16.0.0 -> 172.31.255.255 (Class B subnets) -192.168.0.0 -> 192.168.255.255 (Class C subnets) -.Ed -.Pp -This option is useful in the case that packet aliasing host has both -registered and unregistered subnets on different interfaces. -The registered subnet is fully accessible to the outside world, so traffic -from it does not need to be passed through the packet aliasing engine. -.It Dv PKT_ALIAS_RESET_ON_ADDR_CHANGE -When this mode bit is set and -.Fn PacketAliasSetAddress -is called to change the aliasing address, the internal link table of the -packet aliasing engine will be cleared. -This operating mode is useful for -.Xr ppp 8 -links where the interface address can sometimes change or remain the same -between dial-up attempts. -If this mode bit is not set, the link table will never be reset in the event -of an address change. -.It Dv PKT_ALIAS_PUNCH_FW -This option makes -.Nm -`punch holes' in an -.Xr ipfirewall 4 -based firewall for FTP/IRC DCC connections. -The holes punched are bound by from/to IP address and port; it will not be -possible to use a hole for another connection. -A hole is removed when the connection that uses it dies. -To cater to unexpected death of a program using -.Nm -(e.g. kill -9), -changing the state of the flag will clear the entire firewall range -allocated for holes. -This will also happen on the initial call to -.Fn PacketAliasSetFWBase . -This call must happen prior to setting this flag. -.It Dv PKT_ALIAS_REVERSE -This option makes -.Nm -reverse the way it handles incoming and outgoing packets, allowing it -to be fed with data that passes through the internal interface rather -than the external one. -.It Dv PKT_ALIAS_PROXY_ONLY -This option tells -.Nm -to obey transparent proxy rules only. -Normal packet aliasing is not performed. -See -.Fn PacketAliasProxyRule -below for details. -.El -.Ed -.Pp -.Ft void -.Fn PacketAliasSetFWBase "unsigned int base" "unsigned int num" -.Bd -ragged -offset indent -Set firewall range allocated for punching firewall holes (with the -.Dv PKT_ALIAS_PUNCH_FW -flag). -The range will be cleared for all rules on initialization. -.Ed -.Sh PACKET HANDLING -The packet handling functions are used to modify incoming (remote to local) -and outgoing (local to remote) packets. -The calling program is responsible for receiving and sending packets via -network interfaces. -.Pp -Along with -.Fn PacketAliasInit -and -.Fn PacketAliasSetAddress , -the two packet handling functions, -.Fn PacketAliasIn -and -.Fn PacketAliasOut , -comprise minimal set of functions needed for a basic IP masquerading -implementation. -.Pp -.Ft int -.Fn PacketAliasIn "char *buffer" "int maxpacketsize" -.Bd -ragged -offset indent -An incoming packet coming from a remote machine to the local network is -de-aliased by this function. -The IP packet is pointed to by -.Fa buffer , -and -.Fa maxpacketsize -indicates the size of the data structure containing the packet and should -be at least as large as the actual packet size. -.Pp -Return codes: -.Bl -tag -width indent -.It Dv PKT_ALIAS_OK -The packet aliasing process was successful. -.It Dv PKT_ALIAS_IGNORED -The packet was ignored and not de-aliased. -This can happen if the protocol is unrecognized, possibly an ICMP message -type is not handled or if incoming packets for new connections are being -ignored (if -.Dv PKT_ALIAS_DENY_INCOMING -mode bit was set by -.Fn PacketAliasSetMode ) . -.It Dv PKT_ALIAS_UNRESOLVED_FRAGMENT -This is returned when a fragment cannot be resolved because the header -fragment has not been sent yet. -In this situation, fragments must be saved with -.Fn PacketAliasSaveFragment -until a header fragment is found. -.It Dv PKT_ALIAS_FOUND_HEADER_FRAGMENT -The packet aliasing process was successful, and a header fragment was found. -This is a signal to retrieve any unresolved fragments with -.Fn PacketAliasGetFragment -and de-alias them with -.Fn PacketAliasFragmentIn . -.It Dv PKT_ALIAS_ERROR -An internal error within the packet aliasing engine occurred. -.El -.Ed -.Pp -.Ft int -.Fn PacketAliasOut "char *buffer" "int maxpacketsize" -.Bd -ragged -offset indent -An outgoing packet coming from the local network to a remote machine is -aliased by this function. -The IP packet is pointed to by -.Fa buffer , -and -.Fa maxpacketsize -indicates the maximum packet size permissible should the packet length be -changed. -IP encoding protocols place address and port information in the encapsulated -data stream which has to be modified and can account for changes in packet -length. -Well known examples of such protocols are FTP and IRC DCC. -.Pp -Return codes: -.Bl -tag -width indent -.It Dv PKT_ALIAS_OK -The packet aliasing process was successful. -.It Dv PKT_ALIAS_IGNORED -The packet was ignored and not aliased. -This can happen if the protocol is unrecognized, or possibly an ICMP message -type is not handled. -.It Dv PKT_ALIAS_ERROR -An internal error within the packet aliasing engine occurred. -.El -.Ed -.Sh PORT AND ADDRESS REDIRECTION -The functions described in this section allow machines on the local network -to be accessible in some degree to new incoming connections from the external -network. -Individual ports can be re-mapped or static network address translations can -be designated. -.Pp -.Ft struct alias_link * -.Fo PacketAliasRedirectPort -.Fa "struct in_addr local_addr" -.Fa "u_short local_port" -.Fa "struct in_addr remote_addr" -.Fa "u_short remote_port" -.Fa "struct in_addr alias_addr" -.Fa "u_short alias_port" -.Fa "u_char proto" -.Fc -.Bd -ragged -offset indent -This function specifies that traffic from a given remote address/port to -an alias address/port be redirected to a specified local address/port. -The parameter -.Fa proto -can be either -.Dv IPPROTO_TCP -or -.Dv IPPROTO_UDP , -as defined in -.Aq Pa netinet/in.h . -.Pp -If -.Fa local_addr -or -.Fa alias_addr -is zero, this indicates that the packet aliasing address as established -by -.Fn PacketAliasSetAddress -is to be used. -Even if -.Fn PacketAliasSetAddress -is called to change the address after -.Fn PacketAliasRedirectPort -is called, a zero reference will track this change. -.Pp -If the link is further set up to operate for a load sharing, then -.Fa local_addr -and -.Fa local_port -are ignored, and are selected dynamically from the server pool, as described in -.Fn PacketAliasAddServer -below. -.Pp -If -.Fa remote_addr -is zero, this indicates to redirect packets from any remote address. -Likewise, if -.Fa remote_port -is zero, this indicates to redirect packets originating from any remote -port number. -Almost always, the remote port specification will be zero, but non-zero -remote addresses can sometimes be useful for firewalling. -If two calls to -.Fn PacketAliasRedirectPort -overlap in their address/port specifications, then the most recent call -will have precedence. -.Pp -This function returns a pointer which can subsequently be used by -.Fn PacketAliasRedirectDelete . -If -.Dv NULL -is returned, then the function call did not complete successfully. -.Pp -All port numbers should be in network address byte order, so it is necessary -to use -.Xr htons 3 -to convert these parameters from internally readable numbers to network byte -order. -Addresses are also in network byte order, which is implicit in the use of the -.Fa struct in_addr -data type. -.Ed -.Pp -.Ft struct alias_link * -.Fo PacketAliasRedirectAddr -.Fa "struct in_addr local_addr" -.Fa "struct in_addr alias_addr" -.Fc -.Bd -ragged -offset indent -This function designates that all incoming traffic to -.Fa alias_addr -be redirected to -.Fa local_addr . -Similarly, all outgoing traffic from -.Fa local_addr -is aliased to -.Fa alias_addr . -.Pp -If -.Fa local_addr -or -.Fa alias_addr -is zero, this indicates that the packet aliasing address as established by -.Fn PacketAliasSetAddress -is to be used. -Even if -.Fn PacketAliasSetAddress -is called to change the address after -.Fn PacketAliasRedirectAddr -is called, a zero reference will track this change. -.Pp -If the link is further set up to operate for a load sharing, then -.Fa local_addr -is ignored, and is selected dynamically from the server pool, as described in -.Fn PacketAliasAddServer -below. -.Pp -If subsequent calls to -.Fn PacketAliasRedirectAddr -use the same aliasing address, all new incoming traffic to this aliasing -address will be redirected to the local address made in the last function -call. -New traffic generated by any of the local machines, designated in the -several function calls, will be aliased to the same address. -Consider the following example: -.Bd -literal -offset indent -PacketAliasRedirectAddr(inet_aton("192.168.0.2"), - inet_aton("141.221.254.101")); -PacketAliasRedirectAddr(inet_aton("192.168.0.3"), - inet_aton("141.221.254.101")); -PacketAliasRedirectAddr(inet_aton("192.168.0.4"), - inet_aton("141.221.254.101")); -.Ed -.Pp -Any outgoing connections such as -.Xr telnet 1 -or -.Xr ftp 1 -from 192.168.0.2, 192.168.0.3 and 192.168.0.4 will appear to come from -141.221.254.101. -Any incoming connections to 141.221.254.101 will be directed to 192.168.0.4. -.Pp -Any calls to -.Fn PacketAliasRedirectPort -will have precedence over address mappings designated by -.Fn PacketAliasRedirectAddr . -.Pp -This function returns a pointer which can subsequently be used by -.Fn PacketAliasRedirectDelete . -If -.Dv NULL -is returned, then the function call did not complete successfully. -.Ed -.Pp -.Ft int -.Fo PacketAliasAddServer -.Fa "struct alias_link *link" -.Fa "struct in_addr addr" -.Fa "u_short port" -.Fc -.Bd -ragged -offset indent -This function sets the -.Fa link -up for Load Sharing using IP Network Address Translation (RFC 2391, LSNAT). -LSNAT operates as follows. -A client attempts to access a server by using the server virtual address. -The LSNAT router transparently redirects the request to one of the hosts -in server pool, selected using a real-time load sharing algorithm. -Multiple sessions may be initiated from the same client, and each session -could be directed to a different host based on load balance across server -pool hosts at the time. -If load share is desired for just a few specific services, the configuration -on LSNAT could be defined to restrict load share for just the services -desired. -.Pp -Currently, only the simplest selection algorithm is implemented, where a -host is selected on a round-robin basis only, without regard to load on -the host. -.Pp -First, the -.Fa link -is created by either -.Fn PacketAliasRedirectPort -or -.Fn PacketAliasRedirectAddr . -Then, -.Fn PacketAliasAddServer -is called multiple times to add entries to the -.Fa link Ns 's -server pool. -.Pp -For links created with -.Fn PacketAliasRedirectAddr , -the -.Fa port -argument is ignored and could have any value, e.g. htons(~0). -.Pp -This function returns 0 on success, -1 otherwise. -.Ed -.Pp -.Ft void -.Fn PacketAliasRedirectDelete "struct alias_link *link" -.Bd -ragged -offset indent -This function will delete a specific static redirect rule entered by -.Fn PacketAliasRedirectPort -or -.Fn PacketAliasRedirectAddr . -The parameter -.Fa link -is the pointer returned by either of the redirection functions. -If an invalid pointer is passed to -.Fn PacketAliasRedirectDelete , -then a program crash or unpredictable operation could result, so it is -necessary to be careful using this function. -.Ed -.Pp -.Ft int -.Fn PacketAliasProxyRule "const char *cmd" -.Bd -ragged -offset indent -The passed -.Fa cmd -string consists of one or more pairs of words. -The first word in each pair is a token and the second is the value that -should be applied for that token. -Tokens and their argument types are as follows: -.Bl -tag -width indent -.It Cm type encode_ip_hdr | encode_tcp_stream | no_encode -In order to support transparent proxying, it is necessary to somehow -pass the original address and port information into the new destination -server. -If -.Cm encode_ip_hdr -is specified, the original address and port is passed as an extra IP -option. -If -.Cm encode_tcp_stream -is specified, the original address and port is passed as the first -piece of data in the TCP stream in the format -.Dq DEST Ar IP port . -.It Cm port Ar portnum -Only packets with the destination port -.Ar portnum -are proxied. -.It Cm server Ar host Ns Xo -.Op : Ns Ar portnum -.Xc -This specifies the -.Ar host -and -.Ar portnum -that the data is to be redirected to. -.Ar host -must be an IP address rather than a DNS host name. -If -.Ar portnum -is not specified, the destination port number is not changed. -.Pp -The -.Ar server -specification is mandatory unless the -.Cm delete -command is being used. -.It Cm rule Ar index -Normally, each call to -.Fn PacketAliasProxyRule -inserts the next rule at the start of a linear list of rules. -If an -.Ar index -is specified, the new rule will be checked after all rules with lower -indices. -Calls to -.Fn PacketAliasProxyRule -that do not specify a rule are assigned rule 0. -.It Cm delete Ar index -This token and its argument MUST NOT be used with any other tokens. -When used, all existing rules with the given -.Ar index -are deleted. -.It Cm proto tcp | udp -If specified, only packets of the given protocol type are matched. -.It Cm src Ar IP Ns Xo -.Op / Ns Ar bits -.Xc -If specified, only packets with a source address matching the given -.Ar IP -are matched. -If -.Ar bits -is also specified, then the first -.Ar bits -bits of -.Ar IP -are taken as a network specification, and all IP addresses from that -network will be matched. -.It Cm dst Ar IP Ns Xo -.Op / Ns Ar bits -.Xc -If specified, only packets with a destination address matching the given -.Ar IP -are matched. -If -.Ar bits -is also specified, then the first -.Ar bits -bits of -.Ar IP -are taken as a network specification, and all IP addresses from that -network will be matched. -.El -.Pp -This function is usually used to redirect outgoing connections for -internal machines that are not permitted certain types of internet -access, or to restrict access to certain external machines. -.Ed -.Pp -.Ft struct alias_link * -.Fo PacketAliasRedirectProto -.Fa "struct in_addr local_addr" -.Fa "struct in_addr remote_addr" -.Fa "struct in_addr alias_addr" -.Fa "u_char proto" -.Fc -.Bd -ragged -offset indent -This function specifies that any IP packet with protocol number of -.Fa proto -from a given remote address to an alias address be -redirected to a specified local address. -.Pp -If -.Fa local_addr -or -.Fa alias_addr -is zero, this indicates that the packet aliasing address as established -by -.Fn PacketAliasSetAddress -is to be used. -Even if -.Fn PacketAliasSetAddress -is called to change the address after -.Fn PacketAliasRedirectProto -is called, a zero reference will track this change. -.Pp -If -.Fa remote_addr -is zero, this indicates to redirect packets from any remote address. -Non-zero remote addresses can sometimes be useful for firewalling. -.Pp -If two calls to -.Fn PacketAliasRedirectProto -overlap in their address specifications, then the most recent call -will have precedence. -.Pp -This function returns a pointer which can subsequently be used by -.Fn PacketAliasRedirectDelete . -If -.Dv NULL -is returned, then the function call did not complete successfully. -.Ed -.Sh FRAGMENT HANDLING -The functions in this section are used to deal with incoming fragments. -.Pp -Outgoing fragments are handled within -.Fn PacketAliasOut -by changing the address according to any applicable mapping set by -.Fn PacketAliasRedirectAddr , -or the default aliasing address set by -.Fn PacketAliasSetAddress . -.Pp -Incoming fragments are handled in one of two ways. -If the header of a fragmented IP packet has already been seen, then all -subsequent fragments will be re-mapped in the same manner the header -fragment was. -Fragments which arrive before the header are saved and then retrieved -once the header fragment has been resolved. -.Pp -.Ft int -.Fn PacketAliasSaveFragment "char *ptr" -.Bd -ragged -offset indent -When -.Fn PacketAliasIn -returns -.Dv PKT_ALIAS_UNRESOLVED_FRAGMENT , -this function can be used to save the pointer to the unresolved fragment. -.Pp -It is implicitly assumed that -.Fa ptr -points to a block of memory allocated by -.Xr malloc 3 . -If the fragment is never resolved, the packet aliasing engine will -automatically free the memory after a timeout period. -[Eventually this function should be modified so that a callback function -for freeing memory is passed as an argument.] -.Pp -This function returns -.Dv PKT_ALIAS_OK -if it was successful and -.Dv PKT_ALIAS_ERROR -if there was an error. -.Ed -.Pp -.Ft char * -.Fn PacketAliasGetFragment "char *buffer" -.Bd -ragged -offset indent -This function can be used to retrieve fragment pointers saved by -.Fn PacketAliasSaveFragment . -The IP header fragment pointed to by -.Fa buffer -is the header fragment indicated when -.Fn PacketAliasIn -returns -.Dv PKT_ALIAS_FOUND_HEADER_FRAGMENT . -Once a fragment pointer is retrieved, it becomes the calling program's -responsibility to free the dynamically allocated memory for the fragment. -.Pp -.Fn PacketAliasGetFragment -can be called sequentially until there are no more fragments available, -at which time it returns -.Dv NULL . -.Ed -.Pp -.Ft void -.Fn PacketAliasFragmentIn "char *header" "char *fragment" -.Bd -ragged -offset indent -When a fragment is retrieved with -.Fn PacketAliasGetFragment , -it can then be de-aliased with a call to -.Fn PacketAliasFragmentIn . -The -.Fa header -argument is the pointer to a header fragment used as a template, and -.Fa fragment -is the pointer to the packet to be de-aliased. -.Ed -.Sh MISCELLANEOUS FUNCTIONS -.Ft void -.Fn PacketAliasSetTarget "struct in_addr addr" -.Bd -ragged -offset indent -When an incoming packet not associated with any pre-existing aliasing link -arrives at the host machine, it will be sent to the address indicated by a -call to -.Fn PacketAliasSetTarget . -.Pp -If this function is called with an -.Dv INADDR_NONE -address argument, then all new incoming packets go to the address set by -.Fn PacketAliasSetAddress . -.Pp -If this function is not called, or is called with an -.Dv INADDR_ANY -address argument, then all new incoming packets go to the address specified -in the packet. -This allows external machines to talk directly to internal machines if they -can route packets to the machine in question. -.Ed -.Pp -.Ft int -.Fn PacketAliasCheckNewLink void -.Bd -ragged -offset indent -This function returns a non-zero value when a new aliasing link is created. -In circumstances where incoming traffic is being sequentially sent to -different local servers, this function can be used to trigger when -.Fn PacketAliasSetTarget -is called to change the default target address. -.Ed -.Pp -.Ft u_short -.Fn PacketAliasInternetChecksum "u_short *buffer" "int nbytes" -.Bd -ragged -offset indent -This is a utility function that does not seem to be available elsewhere and -is included as a convenience. -It computes the internet checksum, which is used in both IP and -protocol-specific headers (TCP, UDP, ICMP). -.Pp -The -.Fa buffer -argument points to the data block to be checksummed, and -.Fa nbytes -is the number of bytes. -The 16-bit checksum field should be zeroed before computing the checksum. -.Pp -Checksums can also be verified by operating on a block of data including -its checksum. -If the checksum is valid, -.Fn PacketAliasInternetChecksum -will return zero. -.Ed -.Pp -.Ft int -.Fn PacketUnaliasOut "char *buffer" "int maxpacketsize" -.Bd -ragged -offset indent -An outgoing packet, which has already been aliased, -has its private address/port information restored by this function. -The IP packet is pointed to by -.Fa buffer , -and -.Fa maxpacketsize -is provided for error checking purposes. -This function can be used if an already-aliased packet needs to have its -original IP header restored for further processing (eg. logging). -.Ed -.Sh BUGS -PPTP aliasing does not work when more than one internal client -connects to the same external server at the same time, because -PPTP requires a single TCP control connection to be established -between any two IP addresses. -.Sh AUTHORS -.An Charles Mott Aq cm@linktel.net , -versions 1.0 - 1.8, 2.0 - 2.4. -.An Eivind Eklund Aq eivind@FreeBSD.org , -versions 1.8b, 1.9 and 2.5. -Added IRC DCC support as well as contributing a number of architectural -improvements; added the firewall bypass for FTP/IRC DCC. -.An Erik Salander Aq erik@whistle.com -added support for PPTP and RTSP. -.An Junichi Satoh Aq junichi@junichi.org -added support for RTSP/PNA. -.Sh ACKNOWLEDGMENTS -Listed below, in approximate chronological order, are individuals who -have provided valuable comments and/or debugging assistance. -.Pp -.Bd -ragged -offset indent -.An -split -.An Gary Roberts -.An Tom Torrance -.An Reto Burkhalter -.An Martin Renters -.An Brian Somers -.An Paul Traina -.An Ari Suutari -.An Dave Remien -.An J. Fortes -.An Andrzej Bialecki -.An Gordon Burditt -.Ed -.Sh CONCEPTUAL BACKGROUND -This section is intended for those who are planning to modify the source -code or want to create somewhat esoteric applications using the packet -aliasing functions. -.Pp -The conceptual framework under which the packet aliasing engine operates -is described here. -Central to the discussion is the idea of an -.Em aliasing link -which describes the relationship for a given packet transaction between -the local machine, aliased identity and remote machine. -It is discussed how such links come into existence and are destroyed. -.Ss ALIASING LINKS -There is a notion of an -.Em aliasing link , -which is a 7-tuple describing a specific translation: -.Bd -literal -offset indent -(local addr, local port, alias addr, alias port, - remote addr, remote port, protocol) -.Ed -.Pp -Outgoing packets have the local address and port number replaced with the -alias address and port number. -Incoming packets undergo the reverse process. -The packet aliasing engine attempts to match packets against an internal -table of aliasing links to determine how to modify a given IP packet. -Both the IP header and protocol dependent headers are modified as necessary. -Aliasing links are created and deleted as necessary according to network -traffic. -.Pp -Protocols can be TCP, UDP or even ICMP in certain circumstances. -(Some types of ICMP packets can be aliased according to sequence or ID -number which acts as an equivalent port number for identifying how -individual packets should be handled.) -.Pp -Each aliasing link must have a unique combination of the following five -quantities: alias address/port, remote address/port and protocol. -This ensures that several machines on a local network can share the -same aliasing IP address. -In cases where conflicts might arise, the aliasing port is chosen so that -uniqueness is maintained. -.Ss STATIC AND DYNAMIC LINKS -Aliasing links can either be static or dynamic. -Static links persist indefinitely and represent fixed rules for translating -IP packets. -Dynamic links come into existence for a specific TCP connection or UDP -transaction or ICMP ECHO sequence. -For the case of TCP, the connection can be monitored to see when the -associated aliasing link should be deleted. -Aliasing links for UDP transactions (and ICMP ECHO and TIMESTAMP requests) -work on a simple timeout rule. -When no activity is observed on a dynamic link for a certain amount of time -it is automatically deleted. -Timeout rules also apply to TCP connections which do not open or close -properly. -.Ss PARTIALLY SPECIFIED ALIASING LINKS -Aliasing links can be partially specified, meaning that the remote address -and/or remote port are unknown. -In this case, when a packet matching the incomplete specification is found, -a fully specified dynamic link is created. -If the original partially specified link is dynamic, it will be deleted -after the fully specified link is created, otherwise it will persist. -.Pp -For instance, a partially specified link might be -.Bd -literal -offset indent -(192.168.0.4, 23, 204.228.203.215, 8066, 0, 0, tcp) -.Ed -.Pp -The zeros denote unspecified components for the remote address and port. -If this link were static it would have the effect of redirecting all -incoming traffic from port 8066 of 204.228.203.215 to port 23 (telnet) -of machine 192.168.0.4 on the local network. -Each individual telnet connection would initiate the creation of a distinct -dynamic link. -.Ss DYNAMIC LINK CREATION -In addition to aliasing links, there are also address mappings that can be -stored within the internal data table of the packet aliasing mechanism. -.Bd -literal -offset indent -(local addr, alias addr) -.Ed -.Pp -Address mappings are searched when creating new dynamic links. -.Pp -All outgoing packets from the local network automatically create a dynamic -link if they do not match an already existing fully specified link. -If an address mapping exists for the outgoing packet, this determines -the alias address to be used. -If no mapping exists, then a default address, usually the address of the -packet aliasing host, is used. -If necessary, this default address can be changed as often as each individual -packet arrives. -.Pp -The aliasing port number is determined such that the new dynamic link does -not conflict with any existing links. -In the default operating mode, the packet aliasing engine attempts to set -the aliasing port equal to the local port number. -If this results in a conflict, then port numbers are randomly chosen until -a unique aliasing link can be established. -In an alternate operating mode, the first choice of an aliasing port is also -random and unrelated to the local port number. diff -Nur natd-libalias-orig/natd.c natd-libalias/natd.c --- natd-libalias-orig/natd.c Fri Apr 25 02:50:12 2003 +++ natd-libalias/natd.c Sat Apr 26 22:14:54 2003 @@ -16,7 +16,6 @@ #include #include -#include #include #include @@ -45,7 +44,7 @@ #include #include "natd.h" -struct accept_filter_arg afa; +#include "alias.h" /* * Default values for input and output @@ -87,7 +86,8 @@ static void SetAliasAddressFromIfName (const char *ifName); static void InitiateShutdown (int); static void Shutdown (int); -static void RefreshAddr (int); +static void ReLoad (int); +static void ShowStats (int); static void ParseOption (const char* option, const char* parms); static void ReadConfigFile (const char* fileName); static void SetupPortRedirect (const char* parms); @@ -97,6 +97,7 @@ static u_short StrToPort (const char* str, const char* proto); static int StrToPortRange (const char* str, const char* proto, port_range *portRange); static int StrToProto (const char* str); +static int StrToSched (const char* str); static int StrToAddrAndPortRange (const char* str, struct in_addr* addr, char* proto, port_range *portRange); static void ParseArgs (int argc, char** argv); static void SetupPunchFW(const char *strValue); @@ -123,6 +124,7 @@ static int logDropped; static int logFacility; static int logIpfwDenied; +static const char* filename; int main (int argc, char** argv) { @@ -224,9 +226,6 @@ divertIn = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT); if (divertIn == -1) Quit ("Unable to create incoming divert socket."); - bzero(&afa, sizeof(afa)); - strcpy(afa.af_name, "httpready"); - setsockopt(divertIn, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa)); divertOut = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT); if (divertOut == -1) @@ -289,15 +288,19 @@ * Become a daemon unless verbose mode was requested. */ if (!verbose) - DaemonMode (); + DaemonMode (); /* * Catch signals to manage shutdown and * refresh of interface address. */ siginterrupt(SIGTERM, 1); + siginterrupt(SIGINT, 1); siginterrupt(SIGHUP, 1); + siginterrupt(SIGUSR1, 1); signal (SIGTERM, InitiateShutdown); - signal (SIGHUP, RefreshAddr); + signal (SIGHUP, ReLoad); + signal (SIGINT, InitiateShutdown); + signal (SIGUSR1, ShowStats); /* * Set alias address if it has been given. */ @@ -792,10 +795,17 @@ warn ("%s", msg); } -static void RefreshAddr (int sig) +static void ReLoad (int sig) { if (ifName) assignAliasAddr = 1; + CleanupRedirectList(); + ReadConfigFile(filename); +} + +static void ShowStats (int sig) +{ + ServersStats(); } static void InitiateShutdown (int sig) @@ -1004,7 +1014,7 @@ { RedirectPort, 0, String, - "tcp|udp local_addr:local_port_range[,...] [public_addr:]public_port_range" + "tcp|udp algo local_addr:local_port_range[,...] [public_addr:]public_port_range" " [remote_addr[:remote_port_range]]", "redirect a port (or ports) for incoming traffic", "redirect_port", @@ -1219,6 +1229,7 @@ case ConfigFile: ReadConfigFile (strValue); + filename = strValue; break; case LogDenied: @@ -1352,8 +1363,11 @@ u_short numRemotePorts = 0; int proto; char* protoName; + int sched_type; + char* schedName; char* separator; int i; + int weight = 1 ; struct alias_link *link = NULL; strcpy (buf, parms); @@ -1366,9 +1380,23 @@ proto = StrToProto (protoName); /* + * Extract Load Sharing scheduling + */ +#warning "FIX ME" + schedName = strtok (NULL, " \t"); + if (strlen(schedName) > 5 ) { + fprintf(stderr, "no scheduling choosen, assuming round robin\n"); + sched_type = SCHED_ROUND_ROBIN; + ptr = schedName; + } else { + sched_type = StrToSched (schedName); + ptr = strtok (NULL, " \t"); + } +/* * Extract local address. */ - ptr = strtok (NULL, " \t"); +// ptr = strtok (NULL, " \t"); + if (!ptr) errx (1, "redirect_port: missing local address"); @@ -1385,7 +1413,7 @@ localPort = GETLOPORT(portRange); numLocalPorts = GETNUMPORTS(portRange); serverPool = NULL; - } + } /* * Extract public port and optionally address. @@ -1454,7 +1482,7 @@ htons(remotePortCopy), publicAddr, htons(publicPort + i), - proto,0); + proto, sched_type); } /* @@ -1463,13 +1491,20 @@ if (serverPool != NULL && link != NULL) { ptr = strtok(serverPool, ","); while (ptr != NULL) { + char* strWeight; + strWeight = strchr (ptr, '@'); + if (strWeight) { + *strWeight ='\0'; + ++strWeight; + weight = atoi(strWeight); + } if (StrToAddrAndPortRange(ptr, &localAddr, protoName, &portRange) != 0) errx(1, "redirect_port: invalid local port range"); localPort = GETLOPORT(portRange); if (GETNUMPORTS(portRange) != 1) errx(1, "redirect_port: local port must be single in this context"); - PacketAliasAddServer(link, localAddr, htons(localPort)); + PacketAliasAddServer(link, localAddr, htons(localPort),weight); ptr = strtok(NULL, ","); } } @@ -1539,13 +1574,26 @@ struct in_addr localAddr; struct in_addr publicAddr; char* serverPool; + char* schedName; struct alias_link *link; - + int weight=1; + int sched_type; strcpy (buf, parms); /* * Extract local address. */ - ptr = strtok (buf, " \t"); +#warning "FIX ME" + schedName = strtok (buf, " \t"); + if (strlen(schedName) > 5 ) { + fprintf(stderr, "no scheduling choosen, assuming round robin\n"); + sched_type = SCHED_ROUND_ROBIN; + ptr = schedName; + } else { + sched_type = StrToSched (schedName); + ptr = strtok (NULL, " \t"); + } + +// ptr = strtok (buf, " \t"); if (!ptr) errx (1, "redirect_address: missing local address"); @@ -1565,7 +1613,7 @@ errx (1, "redirect_address: missing public address"); StrToAddr (ptr, &publicAddr); - link = PacketAliasRedirectAddr(localAddr, publicAddr); + link = PacketAliasRedirectAddr(localAddr, publicAddr,weight); /* * Setup LSNAT server pool. @@ -1573,8 +1621,15 @@ if (serverPool != NULL && link != NULL) { ptr = strtok(serverPool, ","); while (ptr != NULL) { + char* strWeight; + strWeight = strchr (ptr, '@'); + if (strWeight) { + *strWeight ='\0'; + ++strWeight; + weight = atoi(strWeight); + } StrToAddr(ptr, &localAddr); - PacketAliasAddServer(link, localAddr, htons(~0)); + PacketAliasAddServer(link, localAddr, htons(~0),weight); ptr = strtok(NULL, ","); } } @@ -1666,6 +1721,20 @@ errx (1, "unknown protocol %s. Expected tcp or udp", str); } +int StrToSched (const char* str) +{ + if (!strcmp (str, "rr")) + return SCHED_ROUND_ROBIN; + + if (!strcmp (str, "wrr")) + return SCHED_WEIGHTED_ROUND_ROBIN; + + if (!strcmp (str, "wsrr")) + return SCHED_SEQ_WEIGHTED_ROUND_ROBIN; + + errx (1, "unknown scheduling %s. Expected rr, wrr, or wsrr", str); +} + int StrToAddrAndPortRange (const char* str, struct in_addr* addr, char* proto, port_range *portRange) { char* ptr; @@ -1692,3 +1761,5 @@ PacketAliasSetFWBase(base, num); (void)PacketAliasSetMode(PKT_ALIAS_PUNCH_FW, PKT_ALIAS_PUNCH_FW); } + + diff -Nur natd-libalias-orig/natd.h natd-libalias/natd.h --- natd-libalias-orig/natd.h Fri Apr 25 02:50:12 2003 +++ natd-libalias/natd.h Fri Apr 25 01:27:17 2003 @@ -22,3 +22,4 @@ extern int SendNeedFragIcmp (int sock, struct ip* failedDgram, int mtu); +#include "alias.h"