#include #include #include #include #include #include #include "util.h" #include "config.h" #include "structs.h" typedef struct listen_ip_priv LISTEN_IP_PRIV; struct listen_ip_priv { LISTEN_IP_PRIV *link; struct sockaddr *sa; socklen_t salen; /* thank you linux...not! */ int af; int socktype; int proto; int fd; } ; extern LEP_OPS lep_ops_ip; static int accept_ip(const struct sockaddr *sa) { switch (sa->sa_family) { case AF_INET: case AF_INET6: return(1); break; } return(0); } static int accept_ip4(const struct sockaddr *sa) { return(sa->sa_family==AF_INET); } static int accept_ip6(const struct sockaddr *sa) { return(sa->sa_family==AF_INET6); } static int lep_ip_add(CONFIG *cfg, LISTEN *l, const char *key, int keylen, const char *rest) { int (*test)(const struct sockaddr *); const char *adjective; const char *slash; char *addrstr; const char *portstr; struct addrinfo hints; struct addrinfo *ai0; struct addrinfo *ai; int e; LISTEN_IP_PRIV *list; LISTEN_IP_PRIV *le; LEP *lep; if ((keylen == 2) && !bcmp(key,"ip",2)) { test = &accept_ip; adjective = "IP"; } else if ((keylen == 3) && !bcmp(key,"ip4",3)) { test = &accept_ip4; adjective = "IPv4"; } else if ((keylen == 3) && !bcmp(key,"ip6",3)) { test = &accept_ip6; adjective = "IPv6"; } else { return(0); } slash = index(rest,'/'); if (slash) { addrstr = blk_to_nulterm(rest,slash-rest); portstr = slash + 1; } else { addrstr = 0; portstr = rest; } hints.ai_flags = 0; hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; hints.ai_addrlen = 0; hints.ai_addr = 0; hints.ai_canonname = 0; hints.ai_next = 0; e = getaddrinfo(addrstr,portstr,&hints,&ai0); free(addrstr); switch (e) { case 0: if (ai0) break; e = EAI_NODATA; /* fall through */ default: config_err(cfg,"error looking up %s: %s",rest,gai_strerror(e)); break; } list = 0; for (ai=ai0;ai;ai=ai->ai_next) { if (! (*test)(ai->ai_addr)) continue; le = malloc(sizeof(LISTEN_IP_PRIV)); le->sa = malloc(ai->ai_addrlen); bcopy(ai->ai_addr,le->sa,ai->ai_addrlen); le->salen = ai->ai_addrlen; le->af = ai->ai_family; le->socktype = ai->ai_socktype; le->proto = ai->ai_protocol; le->fd = -1; le->link = list; list = le; } freeaddrinfo(ai0); if (! list) config_err(cfg,"error looking up %s: no %s addresses",rest,adjective); lep = malloc(sizeof(LEP)); lep->ops = &lep_ops_ip; lep->priv = list; lep->link = l->endpoints; l->endpoints = lep; return(1); } static void lep_ip_free(void *pv) { LISTEN_IP_PRIV *list; LISTEN_IP_PRIV *le; list = pv; while (list) { le = list; list = list->link; free(le->sa); if (le->fd >= 0) close(le->fd); free(le); } } LEP_OPS lep_ops_ip = LEP_OPS_INIT(ip);