commit 6f970988b390633efbe3629fc2c19109f7cf96a3 Author: Steve Dickson <steved@xxxxxxxxxx> Date: Mon Dec 15 11:31:45 2008 -0500 Clients IP address and host names are check on every RPC request, to both mountd and statd when TCP wrappers are enabled. To help this process scale better the access rights are stored in a hash table, which are hashed per IP address, RPC program and procudure numbers. Signed-off-by: Steve Dickson <steved@xxxxxxxxxx> diff --git a/support/misc/tcpwrapper.c b/support/misc/tcpwrapper.c index ceea5ce..f7fd3a9 100644 --- a/support/misc/tcpwrapper.c +++ b/support/misc/tcpwrapper.c @@ -44,6 +44,7 @@ #include <pwd.h> #include <sys/types.h> #include <sys/signal.h> +#include <sys/queue.h> #ifdef SYSV40 #include <netinet/in.h> #include <rpc/rpcent.h> @@ -89,6 +90,76 @@ int hosts_ctl(char *daemon, char *name, char *addr, char *user) #define ALLOW 1 #define DENY 0 +typedef struct _haccess_t { + TAILQ_ENTRY(_haccess_t) list; + int access; + struct in_addr addr; +} haccess_t; + +#define HASH_TABLE_SIZE 1021 +typedef struct _hash_head { + TAILQ_HEAD(host_list, _haccess_t) h_head; +} hash_head; +hash_head haccess_tbl[HASH_TABLE_SIZE]; +static haccess_t *haccess_lookup(struct sockaddr_in *addr, u_long, u_long); +static void haccess_add(struct sockaddr_in *addr, u_long, u_long, int); + +inline unsigned int strtoint(char *str) +{ + unsigned int n = 0; + int len = strlen(str); + int i; + + for (i=0; i < len; i++) + n+=((int)str[i])*i; + + return n; +} +inline int hashint(unsigned int num) +{ + return num % HASH_TABLE_SIZE; +} +#define HASH(_addr, _proc, _prog) \ + hashint((strtoint((_addr))+(_proc)+(_prog))) + +void haccess_add(struct sockaddr_in *addr, u_long proc, + u_long prog, int access) +{ + hash_head *head; + haccess_t *hptr; + int hash; + + hptr = (haccess_t *)malloc(sizeof(haccess_t)); + if (hptr == NULL) + return; + + hash = HASH(inet_ntoa(addr->sin_addr), proc, prog); + head = &(haccess_tbl[hash]); + + hptr->access = access; + hptr->addr.s_addr = addr->sin_addr.s_addr; + + if (TAILQ_EMPTY(&head->h_head)) + TAILQ_INSERT_HEAD(&head->h_head, hptr, list); + else + TAILQ_INSERT_TAIL(&head->h_head, hptr, list); +} +haccess_t *haccess_lookup(struct sockaddr_in *addr, u_long proc, u_long prog) +{ + hash_head *head; + haccess_t *hptr; + int hash; + + hash = HASH(inet_ntoa(addr->sin_addr), proc, prog); + head = &(haccess_tbl[hash]); + + TAILQ_FOREACH(hptr, &head->h_head, list) { + if (hptr->addr.s_addr == addr->sin_addr.s_addr) + return hptr; + } + return NULL; +} + int good_client(daemon, addr) char *daemon; @@ -184,13 +255,21 @@ struct sockaddr_in *addr; u_long proc; u_long prog; { + haccess_t *acc = NULL; + + acc = haccess_lookup(addr, proc, prog); + if (acc) + return (acc->access); + if (!(from_local(addr) || good_client(daemon, addr))) { log_bad_host(addr, proc, prog); + haccess_add(addr, proc, prog, FALSE); return (FALSE); } if (verboselog) log_client(addr, proc, prog); + haccess_add(addr, proc, prog, TRUE); return (TRUE); } -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html