static void resolve_host(char **parv) { struct dns_request *req; char *requestid = parv[1]; char *iptype = parv[2]; char *rec = parv[3]; int flags; req = rb_malloc(sizeof(struct dns_request)); strcpy(req->reqid, requestid); req->revfwd = REQFWD; req->reqtype = FWDHOST; switch (*iptype) { case 6: flags = T_AAAA; break; default: flags = T_A; break; } req->query.ptr = req; req->query.callback = send_answer; gethost_byname_type(rec, &req->query, flags); }
/* A bit different from ircd... you just get a dns_query object. * * It gets freed whenever the res code gets back to us. */ struct dns_query * lookup_ip(const char *host, int aftype, DNSCB callback, void *data) { struct dns_query *query = rb_malloc(sizeof(struct dns_query)); int g_type; if(aftype == AF_INET) { query->type = QUERY_A; g_type = T_A; } else if(aftype == AF_INET6) { query->type = QUERY_AAAA; g_type = T_AAAA; } else { rb_free(query); return NULL; } query->id = query_count++; query->callback = callback; query->data = data; query->query.ptr = query; query->query.callback = handle_lookup_ip_reply; gethost_byname_type(host, &query->query, g_type); return query; }
static void os_cmd_resolve(sourceinfo_t *si, int parc, char *parv[]) { resolve_req_t *req; if (request_heap == NULL) request_heap = mowgli_heap_create(sizeof(resolve_req_t), 32, BH_LAZY); if (!parv[0]) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "RESOLVE"); return; } req = mowgli_heap_alloc(request_heap); req->si = si; req->dns_query.ptr = req; req->dns_query.callback = resolve_cb; gethost_byname_type(parv[0], &req->dns_query, T_A); object_ref(req->si); }
/* * 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); } }
/* * 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; #ifdef IPV6 if (aftype == AF_INET6) gethost_byname_type(host, F->dns_query, T_AAAA); else #endif gethost_byname_type(host, F->dns_query, T_A); } 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); } }