/* 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(const char *arg) { struct addrinfo hints, *res; /* Done max number of nameservers? */ if (irc_nscount >= IRCD_MAXNS) { ilog (L_MAIN, "Too many nameservers, ignoring %s", arg); return; } ilog (L_MAIN, "Using nameserver: %s", arg); memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; if (getaddrinfo(arg, "domain", &hints, &res)) return; if (res == NULL) return; memcpy(&irc_nsaddr_list[irc_nscount], res->ai_addr, res->ai_addrlen); SET_SS_LEN(&irc_nsaddr_list[irc_nscount], res->ai_addrlen); irc_nscount++; freeaddrinfo(res); }
/* * add_listener- create a new listener * port - the port number to listen on * vhost_ip - if non-null must contain a valid IP address string in * the format "255.255.255.255" */ void add_listener(int port, const char *vhost_ip, int family, int ssl) { struct Listener *listener; struct rb_sockaddr_storage vaddr; /* * if no port in conf line, don't bother */ if(port == 0) return; memset(&vaddr, 0, sizeof(vaddr)); vaddr.ss_family = family; if(vhost_ip != NULL) { if(family == AF_INET) { if(rb_inet_pton(family, vhost_ip, &((struct sockaddr_in *)&vaddr)->sin_addr) <= 0) return; } #ifdef RB_IPV6 else { if(rb_inet_pton(family, vhost_ip, &((struct sockaddr_in6 *)&vaddr)->sin6_addr) <= 0) return; } #endif } else { switch(family) { case AF_INET: ((struct sockaddr_in *)&vaddr)->sin_addr.s_addr = INADDR_ANY; break; #ifdef RB_IPV6 case AF_INET6: memcpy(&((struct sockaddr_in6 *)&vaddr)->sin6_addr, &in6addr_any, sizeof(struct in6_addr)); break; default: return; #endif } } switch(family) { case AF_INET: SET_SS_LEN(&vaddr, sizeof(struct sockaddr_in)); ((struct sockaddr_in *)&vaddr)->sin_port = htons(port); break; #ifdef RB_IPV6 case AF_INET6: SET_SS_LEN(&vaddr, sizeof(struct sockaddr_in6)); ((struct sockaddr_in6 *)&vaddr)->sin6_port = htons(port); break; #endif default: break; } if((listener = find_listener(&vaddr))) { if(listener->F != NULL) return; } else { listener = make_listener(&vaddr); listener->next = ListenerPollList; ListenerPollList = listener; } listener->F = NULL; listener->ssl = ssl; if(inetport(listener)) listener->active = 1; else close_listener(listener); }
/* * void comm_connect_tcp(int fd, const char *host, u_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(int fd, const char *host, u_short port, struct sockaddr *clocal, int socklen, CNCB * callback, void *data, int aftype, int timeout) { void *ipptr = NULL; fde_t *F; s_assert(fd >= 0); F = &fd_table[fd]; F->flags.called_connect = 1; s_assert(callback); F->connect.callback = callback; F->connect.data = data; memset(&F->connect.hostaddr, 0, sizeof(F->connect.hostaddr)); #ifdef IPV6 if(aftype == AF_INET6) { struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&F->connect.hostaddr; SET_SS_LEN(F->connect.hostaddr, sizeof(struct sockaddr_in6)); in6->sin6_port = htons(port); in6->sin6_family = AF_INET6; ipptr = &in6->sin6_addr; } else #endif { struct sockaddr_in *in = (struct sockaddr_in *)&F->connect.hostaddr; SET_SS_LEN(F->connect.hostaddr, sizeof(struct sockaddr_in)); in->sin_port = htons(port); in->sin_family = AF_INET; ipptr = &in->sin_addr; } /* 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(F->fd, clocal, socklen) < 0)) { /* Failure, call the callback with COMM_ERR_BIND */ comm_connect_callback(F->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(). */ if(inetpton(aftype, host, ipptr) <= 0) { /* Send the DNS request, for the next level */ F->dns_query = MyMalloc(sizeof(struct DNSQuery)); F->dns_query->ptr = F; F->dns_query->callback = comm_connect_dns_callback; adns_gethost(host, aftype, F->dns_query); } else { /* We have a valid IP, so we just call tryconnect */ /* Make sure we actually set the timeout here .. */ comm_settimeout(F->fd, timeout * 1000, comm_connect_timeout, NULL); comm_connect_tryconnect(F->fd, NULL); } }