/* add_nameserver() * * input - either an IPV4 address in dotted quad * or an IPV6 address in : format * output - NONE * side effects - entry in irc_nsaddr_list is filled in as needed */ static void add_nameserver(char *arg) { struct addrinfo hints, *res; /* Done max number of nameservers? */ if ((irc_nscount + 1) >= IRCD_MAXNS) return; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; if (irc_getaddrinfo(arg, "domain", &hints, &res)) return; if (res == NULL) return; memcpy(&irc_nsaddr_list[irc_nscount].ss, res->ai_addr, res->ai_addrlen); irc_nsaddr_list[irc_nscount].ss_len = res->ai_addrlen; irc_nscount++; irc_freeaddrinfo(res); }
/* match_cidr() * * Input - mask, address * Ouput - 1 = Matched 0 = Did not match */ int match_cidr(const char *s1, const char *s2) { struct irc_ssaddr ipaddr, maskaddr; char address[NICKLEN + USERLEN + HOSTLEN + 6]; char mask[NICKLEN + USERLEN + HOSTLEN + 6]; char *ipmask, *ip, *len; int cidrlen, aftype; struct addrinfo hints, *res; /* Unlikely to ever overflow, but we may as well be consistant - stu */ strlcpy(mask, s1, sizeof(mask)); strlcpy(address, s2, sizeof(address)); ipmask = strrchr(mask, '@'); if (ipmask == NULL) return(0); *ipmask++ = '\0'; ip = strrchr(address, '@'); if (ip == NULL) return(0); *ip++ = '\0'; len = strrchr(ipmask, '/'); if (len == NULL) return(0); *len++ = '\0'; cidrlen = atoi(len); if (cidrlen == 0) return(0); #ifdef IPV6 if (strchr(ip, ':') && strchr(ipmask, ':')) aftype = AF_INET6; else #endif if (!strchr(ip, ':') && !strchr(ipmask, ':')) aftype = AF_INET; else return(0); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_flags = AI_NUMERICHOST; irc_getaddrinfo(ip, NULL, &hints, &res); if (res) { memcpy(&ipaddr, res->ai_addr, res->ai_addrlen); ipaddr.ss_len = res->ai_addrlen; ipaddr.ss.ss_family = res->ai_family; irc_freeaddrinfo(res); } irc_getaddrinfo(ipmask, NULL, &hints, &res); if (res) { memcpy(&maskaddr, res->ai_addr, res->ai_addrlen); maskaddr.ss_len = res->ai_addrlen; maskaddr.ss.ss_family = res->ai_family; irc_freeaddrinfo(res); } if (comp_with_mask(&ipaddr, &maskaddr, cidrlen) && match(mask, address)) return(1); else return(0); }
/* * void comm_connect_tcp(int fd, const char *host, unsigned short port, * struct sockaddr *clocal, int socklen, * CNCB *callback, void *data, int aftype, int timeout) * Input: An fd to connect with, a host and port to connect to, * a local sockaddr to connect from + length(or NULL to use the * default), a callback, the data to pass into the callback, the * address family. * Output: None. * Side-effects: A non-blocking connection to the host is started, and * if necessary, set up for selection. The callback given * may be called now, or it may be called later. */ void comm_connect_tcp(fde_t *fd, const char *host, unsigned short port, struct sockaddr *clocal, int socklen, CNCB *callback, void *data, int aftype, int timeout) { struct addrinfo hints, *res; char portname[PORTNAMELEN+1]; assert(callback); fd->connect.callback = callback; fd->connect.data = data; fd->connect.hostaddr.ss.ss_family = aftype; fd->connect.hostaddr.ss_port = htons(port); /* Note that we're using a passed sockaddr here. This is because * generally you'll be bind()ing to a sockaddr grabbed from * getsockname(), so this makes things easier. * XXX If NULL is passed as local, we should later on bind() to the * virtual host IP, for completeness. * -- adrian */ if ((clocal != NULL) && (bind(fd->fd, clocal, socklen) < 0)) { /* Failure, call the callback with COMM_ERR_BIND */ comm_connect_callback(fd, COMM_ERR_BIND); /* ... and quit */ return; } /* Next, if we have been given an IP, get the addr and skip the * DNS check (and head direct to comm_connect_tryconnect(). */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; snprintf(portname, PORTNAMELEN, "%d", port); if (irc_getaddrinfo(host, portname, &hints, &res)) { /* Send the DNS request, for the next level */ fd->dns_query = MyMalloc(sizeof(struct DNSQuery)); fd->dns_query->ptr = fd; fd->dns_query->callback = comm_connect_dns_callback; if (aftype == AF_INET6) gethost_byname_type(host, fd->dns_query, T_AAAA); else gethost_byname_type(host, fd->dns_query, T_A); } else { /* We have a valid IP, so we just call tryconnect */ /* Make sure we actually set the timeout here .. */ assert(res != NULL); memcpy(&fd->connect.hostaddr, res->ai_addr, res->ai_addrlen); fd->connect.hostaddr.ss_len = res->ai_addrlen; fd->connect.hostaddr.ss.ss_family = res->ai_family; irc_freeaddrinfo(res); comm_settimeout(fd, timeout*1000, comm_connect_timeout, NULL); comm_connect_tryconnect(fd, NULL); } }