diff --git a/lib/libalias/alias.h b/lib/libalias/alias.h index 2285d97e3072..9f15579832a2 100644 --- a/lib/libalias/alias.h +++ b/lib/libalias/alias.h @@ -51,6 +51,11 @@ struct alias_link; struct in_addr, u_short, u_char); + extern int + PacketAliasAddServer(struct alias_link *link, + struct in_addr addr, + u_short port); + extern int PacketAliasPptp(struct in_addr); diff --git a/lib/libalias/alias_db.c b/lib/libalias/alias_db.c index 431a757540a5..bc020f35e4b4 100644 --- a/lib/libalias/alias_db.c +++ b/lib/libalias/alias_db.c @@ -237,6 +237,13 @@ struct tcp_dat int fwhole; /* Which firewall record is used for this hole? */ }; +struct server /* LSNAT server pool (circular list) */ +{ + struct in_addr addr; + u_short port; + struct server *next; +}; + struct alias_link /* Main data structure */ { struct in_addr src_addr; /* Address and port information */ @@ -247,6 +254,7 @@ struct alias_link /* Main data structure */ u_short dst_port; u_short alias_port; u_short proxy_port; + struct server *server; int link_type; /* Type of link: TCP, UDP, ICMP, PPTP, frag */ @@ -778,6 +786,17 @@ DeleteLink(struct alias_link *link) ClearFWHole(link); #endif +/* Free memory allocated for LSNAT server pool */ + if (link->server != NULL) { + struct server *head, *curr, *next; + + head = curr = link->server; + do { + next = curr->next; + free(curr); + } while ((curr = next) != head); + } + /* Adjust output table pointers */ link_last = link->last_out; link_next = link->next_out; @@ -871,6 +890,7 @@ AddLink(struct in_addr src_addr, link->src_port = src_port; link->dst_port = dst_port; link->proxy_port = 0; + link->server = NULL; link->link_type = link_type; link->sockfd = -1; link->flags = 0; @@ -1044,6 +1064,7 @@ _FindLinkOut(struct in_addr src_addr, while (link != NULL) { if (link->src_addr.s_addr == src_addr.s_addr + && link->server == NULL && link->dst_addr.s_addr == dst_addr.s_addr && link->dst_port == dst_port && link->src_port == src_port @@ -1207,39 +1228,39 @@ _FindLinkIn(struct in_addr dst_addr, if (link_fully_specified != NULL) { link_fully_specified->timestamp = timeStamp; - return link_fully_specified; + link = link_fully_specified; } else if (link_unknown_dst_port != NULL) - { - return replace_partial_links - ? ReLink(link_unknown_dst_port, - link_unknown_dst_port->src_addr, dst_addr, alias_addr, - link_unknown_dst_port->src_port, dst_port, alias_port, - link_type) - : link_unknown_dst_port; - } + link = link_unknown_dst_port; else if (link_unknown_dst_addr != NULL) - { - return replace_partial_links - ? ReLink(link_unknown_dst_addr, - link_unknown_dst_addr->src_addr, dst_addr, alias_addr, - link_unknown_dst_addr->src_port, dst_port, alias_port, - link_type) - : link_unknown_dst_addr; - } + link = link_unknown_dst_addr; else if (link_unknown_all != NULL) - { - return replace_partial_links - ? ReLink(link_unknown_all, - link_unknown_all->src_addr, dst_addr, alias_addr, - link_unknown_all->src_port, dst_port, alias_port, - link_type) - : link_unknown_all; - } + link = link_unknown_all; else + return (NULL); + + if (replace_partial_links && + (link->flags & LINK_PARTIALLY_SPECIFIED || link->server != NULL)) { - return(NULL); + 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; + } 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, + link_type); } + + return (link); } static struct alias_link * @@ -1527,7 +1548,13 @@ FindOriginalAddress(struct in_addr alias_addr) } else { - if (link->src_addr.s_addr == INADDR_ANY) + 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; @@ -2035,6 +2062,7 @@ UninitPacketAliasLog(void) -- "outside world" means other than alias*.c routines -- PacketAliasRedirectPort() + PacketAliasAddServer() PacketAliasRedirectPptp() PacketAliasRedirectAddr() PacketAliasRedirectDelete() @@ -2092,6 +2120,36 @@ PacketAliasRedirectPort(struct in_addr src_addr, u_short src_port, return link; } +/* Add server to the pool of servers */ +int +PacketAliasAddServer(struct alias_link *link, struct in_addr addr, u_short port) +{ + struct server *server; + + server = malloc(sizeof(struct server)); + + if (server != NULL) { + struct server *head; + + server->addr = addr; + server->port = port; + + head = link->server; + if (head == NULL) + server->next = server; + else { + struct server *s; + + for (s = head; s->next != head; s = s->next); + s->next = server; + server->next = head; + } + link->server = server; + return (0); + } else + return (-1); +} + /* Translate PPTP packets to a machine on the inside * XXX This function is made obsolete by PacketAliasRedirectPptp(). */ diff --git a/lib/libalias/libalias.3 b/lib/libalias/libalias.3 index 42840af9bf7b..36788d5fe834 100644 --- a/lib/libalias/libalias.3 +++ b/lib/libalias/libalias.3 @@ -376,6 +376,14 @@ 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. @@ -434,6 +442,12 @@ 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 @@ -471,6 +485,52 @@ If 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 diff --git a/sys/netinet/libalias/alias.h b/sys/netinet/libalias/alias.h index 2285d97e3072..9f15579832a2 100644 --- a/sys/netinet/libalias/alias.h +++ b/sys/netinet/libalias/alias.h @@ -51,6 +51,11 @@ struct alias_link; struct in_addr, u_short, u_char); + extern int + PacketAliasAddServer(struct alias_link *link, + struct in_addr addr, + u_short port); + extern int PacketAliasPptp(struct in_addr); diff --git a/sys/netinet/libalias/alias_db.c b/sys/netinet/libalias/alias_db.c index 431a757540a5..bc020f35e4b4 100644 --- a/sys/netinet/libalias/alias_db.c +++ b/sys/netinet/libalias/alias_db.c @@ -237,6 +237,13 @@ struct tcp_dat int fwhole; /* Which firewall record is used for this hole? */ }; +struct server /* LSNAT server pool (circular list) */ +{ + struct in_addr addr; + u_short port; + struct server *next; +}; + struct alias_link /* Main data structure */ { struct in_addr src_addr; /* Address and port information */ @@ -247,6 +254,7 @@ struct alias_link /* Main data structure */ u_short dst_port; u_short alias_port; u_short proxy_port; + struct server *server; int link_type; /* Type of link: TCP, UDP, ICMP, PPTP, frag */ @@ -778,6 +786,17 @@ DeleteLink(struct alias_link *link) ClearFWHole(link); #endif +/* Free memory allocated for LSNAT server pool */ + if (link->server != NULL) { + struct server *head, *curr, *next; + + head = curr = link->server; + do { + next = curr->next; + free(curr); + } while ((curr = next) != head); + } + /* Adjust output table pointers */ link_last = link->last_out; link_next = link->next_out; @@ -871,6 +890,7 @@ AddLink(struct in_addr src_addr, link->src_port = src_port; link->dst_port = dst_port; link->proxy_port = 0; + link->server = NULL; link->link_type = link_type; link->sockfd = -1; link->flags = 0; @@ -1044,6 +1064,7 @@ _FindLinkOut(struct in_addr src_addr, while (link != NULL) { if (link->src_addr.s_addr == src_addr.s_addr + && link->server == NULL && link->dst_addr.s_addr == dst_addr.s_addr && link->dst_port == dst_port && link->src_port == src_port @@ -1207,39 +1228,39 @@ _FindLinkIn(struct in_addr dst_addr, if (link_fully_specified != NULL) { link_fully_specified->timestamp = timeStamp; - return link_fully_specified; + link = link_fully_specified; } else if (link_unknown_dst_port != NULL) - { - return replace_partial_links - ? ReLink(link_unknown_dst_port, - link_unknown_dst_port->src_addr, dst_addr, alias_addr, - link_unknown_dst_port->src_port, dst_port, alias_port, - link_type) - : link_unknown_dst_port; - } + link = link_unknown_dst_port; else if (link_unknown_dst_addr != NULL) - { - return replace_partial_links - ? ReLink(link_unknown_dst_addr, - link_unknown_dst_addr->src_addr, dst_addr, alias_addr, - link_unknown_dst_addr->src_port, dst_port, alias_port, - link_type) - : link_unknown_dst_addr; - } + link = link_unknown_dst_addr; else if (link_unknown_all != NULL) - { - return replace_partial_links - ? ReLink(link_unknown_all, - link_unknown_all->src_addr, dst_addr, alias_addr, - link_unknown_all->src_port, dst_port, alias_port, - link_type) - : link_unknown_all; - } + link = link_unknown_all; else + return (NULL); + + if (replace_partial_links && + (link->flags & LINK_PARTIALLY_SPECIFIED || link->server != NULL)) { - return(NULL); + 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; + } 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, + link_type); } + + return (link); } static struct alias_link * @@ -1527,7 +1548,13 @@ FindOriginalAddress(struct in_addr alias_addr) } else { - if (link->src_addr.s_addr == INADDR_ANY) + 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; @@ -2035,6 +2062,7 @@ UninitPacketAliasLog(void) -- "outside world" means other than alias*.c routines -- PacketAliasRedirectPort() + PacketAliasAddServer() PacketAliasRedirectPptp() PacketAliasRedirectAddr() PacketAliasRedirectDelete() @@ -2092,6 +2120,36 @@ PacketAliasRedirectPort(struct in_addr src_addr, u_short src_port, return link; } +/* Add server to the pool of servers */ +int +PacketAliasAddServer(struct alias_link *link, struct in_addr addr, u_short port) +{ + struct server *server; + + server = malloc(sizeof(struct server)); + + if (server != NULL) { + struct server *head; + + server->addr = addr; + server->port = port; + + head = link->server; + if (head == NULL) + server->next = server; + else { + struct server *s; + + for (s = head; s->next != head; s = s->next); + s->next = server; + server->next = head; + } + link->server = server; + return (0); + } else + return (-1); +} + /* Translate PPTP packets to a machine on the inside * XXX This function is made obsolete by PacketAliasRedirectPptp(). */ diff --git a/sys/netinet/libalias/libalias.3 b/sys/netinet/libalias/libalias.3 index 42840af9bf7b..36788d5fe834 100644 --- a/sys/netinet/libalias/libalias.3 +++ b/sys/netinet/libalias/libalias.3 @@ -376,6 +376,14 @@ 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. @@ -434,6 +442,12 @@ 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 @@ -471,6 +485,52 @@ If 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