/* sfd has been marked for reading, handle the read and process the packet */ static int process_incoming_pkt() { struct sockaddr_in6 from; /* Whois the one sending us data? */ socklen_t len_from = sizeof(from); char buf[MAX_PKT_LEN]; /* Max allowed packet size for the protocol */ int len; /* Actual received packet size */ if ((len = recvfrom(sfd, buf, MAX_PKT_LEN, 0, (struct sockaddr *)&from, &len_from)) <= 0) { /* Ignore if we have been interrupted by a signal, * or if select marked sfd as ready for reading * without any no data available. */ if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) return EXIT_SUCCESS; /* Real error, abort mission */ perror("recv failed"); return EXIT_FAILURE; } /* Check packet consistency */ if (len < 4) { printf("Received malformed data, shutting down!\n"); return EXIT_FAILURE; } /* We need to track who is sending us data, so that we can send him the * reverse traffic coming from the host we're proxying */ if (!has_source_addr) { memcpy(&src_addr, &from, sizeof(src_addr)); fprintf(stderr, "@@ Remote host is %s [%d]\n", sockaddr6_to_human(&from.sin6_addr), ntohs(from.sin6_port)); has_source_addr = 1; /* We're logically connected to that guy */ } /* Simply relay packets from the host we're proxying */ if (!sockaddr_cmp(&from, &dest_addr)) { /* Forward reverse-traffic */ if (sendto(sfd, buf, len, 0, (struct sockaddr*)&src_addr, sizeof(src_addr)) != len) { perror("Failed to relay a message back to the source"); return EXIT_FAILURE; } return EXIT_SUCCESS; } else if (sockaddr_cmp(&from, &src_addr)) { /* We do not know the guy that sent us this data, ignore him */ fprintf(stderr, "@@ Received %d bytes from %s [%d], " "which is an alien to the connection. Dropping it!\n", len, sockaddr6_to_human(&from.sin6_addr), ntohs(from.sin6_port)); return EXIT_SUCCESS; } /* We have valid data, simulate the behavior of a lossy link * before delivery */ return simulate_link(buf, len); }
static int gateway_cmp(struct pingu_route *a, struct pingu_route *b) { int r; if (a->dst_len != b->dst_len) return a->dst_len - b->dst_len; r = sockaddr_cmp(&a->dest, &b->dest); if (r != 0) return r; r = sockaddr_cmp(&a->gw_addr, &b->gw_addr); if (r != 0) return r; return a->metric - b->metric; }
/** * Find the range that matches this pending message. * @param runtime: runtime with current moment, and range list. * @param entry: returns the pointer to entry that matches. * @param pend: the pending that the entry must match. * @return: true if a match is found. */ static int pending_find_match(struct replay_runtime* runtime, struct entry** entry, struct fake_pending* pend) { int timenow = runtime->now->time_step; struct replay_range* p = runtime->scenario->range_list; while(p) { if(p->start_step <= timenow && timenow <= p->end_step && (p->addrlen == 0 || sockaddr_cmp(&p->addr, p->addrlen, &pend->addr, pend->addrlen) == 0) && (*entry = find_match(p->match, pend->pkt, pend->pkt_len, pend->transport))) { log_info("matched query time %d in range [%d, %d] " "with entry line %d", timenow, p->start_step, p->end_step, (*entry)->lineno); if(p->addrlen != 0) log_addr(0, "matched ip", &p->addr, p->addrlen); log_pkt("matched pkt: ", (*entry)->reply_list->reply_pkt, (*entry)->reply_list->reply_len); return 1; } p = p->next_range; } return 0; }
struct waiting_tcp* pending_tcp_query(struct outside_network* outnet, ldns_buffer* packet, struct sockaddr_storage* addr, socklen_t addrlen, int timeout, comm_point_callback_t* callback, void* callback_arg) { struct replay_runtime* runtime = (struct replay_runtime*)outnet->base; struct fake_pending* pend = (struct fake_pending*)calloc(1, sizeof(struct fake_pending)); ldns_status status; log_assert(pend); pend->buffer = ldns_buffer_new(ldns_buffer_capacity(packet)); log_assert(pend->buffer); ldns_buffer_write(pend->buffer, ldns_buffer_begin(packet), ldns_buffer_limit(packet)); ldns_buffer_flip(pend->buffer); memcpy(&pend->addr, addr, addrlen); pend->addrlen = addrlen; pend->callback = callback; pend->cb_arg = callback_arg; pend->timeout = timeout; pend->transport = transport_tcp; pend->pkt = NULL; pend->runtime = runtime; pend->serviced = 0; status = ldns_buffer2pkt_wire(&pend->pkt, packet); if(status != LDNS_STATUS_OK) { log_err("ldns error parsing tcp output packet: %s", ldns_get_errorstr_by_id(status)); fatal_exit("Sending unparseable DNS packets to servers!"); } log_pkt("pending tcp pkt: ", pend->pkt); /* see if it matches the current moment */ if(runtime->now && runtime->now->evt_type == repevt_back_query && (runtime->now->addrlen == 0 || sockaddr_cmp( &runtime->now->addr, runtime->now->addrlen, &pend->addr, pend->addrlen) == 0) && find_match(runtime->now->match, pend->pkt, pend->transport)) { log_info("testbound: matched pending to event. " "advance time between events."); log_info("testbound: do STEP %d %s", runtime->now->time_step, repevt_string(runtime->now->evt_type)); advance_moment(runtime); /* still create the pending, because we need it to callback */ } log_info("testbound: created fake pending"); /* add to list */ pend->next = runtime->pending_list; runtime->pending_list = pend; return (struct waiting_tcp*)pend; }
struct waiting_tcp* pending_tcp_query(struct outside_network* outnet, sldns_buffer* packet, struct sockaddr_storage* addr, socklen_t addrlen, int timeout, comm_point_callback_t* callback, void* callback_arg, int ATTR_UNUSED(ssl_upstream)) { struct replay_runtime* runtime = (struct replay_runtime*)outnet->base; struct fake_pending* pend = (struct fake_pending*)calloc(1, sizeof(struct fake_pending)); log_assert(pend); pend->buffer = sldns_buffer_new(sldns_buffer_capacity(packet)); log_assert(pend->buffer); sldns_buffer_write(pend->buffer, sldns_buffer_begin(packet), sldns_buffer_limit(packet)); sldns_buffer_flip(pend->buffer); memcpy(&pend->addr, addr, addrlen); pend->addrlen = addrlen; pend->callback = callback; pend->cb_arg = callback_arg; pend->timeout = timeout; pend->transport = transport_tcp; pend->pkt = NULL; pend->zone = NULL; pend->runtime = runtime; pend->serviced = 0; pend->pkt_len = sldns_buffer_limit(packet); pend->pkt = memdup(sldns_buffer_begin(packet), pend->pkt_len); if(!pend->pkt) fatal_exit("out of memory"); log_pkt("pending tcp pkt: ", pend->pkt, pend->pkt_len); /* see if it matches the current moment */ if(runtime->now && runtime->now->evt_type == repevt_back_query && (runtime->now->addrlen == 0 || sockaddr_cmp( &runtime->now->addr, runtime->now->addrlen, &pend->addr, pend->addrlen) == 0) && find_match(runtime->now->match, pend->pkt, pend->pkt_len, pend->transport)) { log_info("testbound: matched pending to event. " "advance time between events."); log_info("testbound: do STEP %d %s", runtime->now->time_step, repevt_string(runtime->now->evt_type)); advance_moment(runtime); /* still create the pending, because we need it to callback */ } log_info("testbound: created fake pending"); /* add to list */ pend->next = runtime->pending_list; runtime->pending_list = pend; return (struct waiting_tcp*)pend; }
int infra_compfunc(void* key1, void* key2) { struct infra_key* k1 = (struct infra_key*)key1; struct infra_key* k2 = (struct infra_key*)key2; int r = sockaddr_cmp(&k1->addr, k1->addrlen, &k2->addr, k2->addrlen); if(r != 0) return r; if(k1->namelen != k2->namelen) { if(k1->namelen < k2->namelen) return -1; return 1; } return query_dname_compare(k1->zonename, k2->zonename); }
/** find or else create proxy for this remote client */ static struct proxy* find_create_proxy(struct sockaddr_storage* from, socklen_t from_len, fd_set* rorig, int* max, struct proxy** proxies, int serv_ip6, struct timeval* now, struct timeval* reuse_timeout) { struct proxy* p; struct timeval t; for(p = *proxies; p; p = p->next) { if(sockaddr_cmp(from, from_len, &p->addr, p->addr_len)==0) return p; } /* possibly: reuse lapsed entries */ for(p = *proxies; p; p = p->next) { if(p->numwait > p->numsent || p->numsent > p->numreturn) continue; t = *now; dl_tv_subtract(&t, &p->lastuse); if(dl_tv_smaller(&t, reuse_timeout)) continue; /* yes! */ verbose(1, "reuse existing entry"); memmove(&p->addr, from, from_len); p->addr_len = from_len; p->numreuse++; return p; } /* create new */ p = (struct proxy*)calloc(1, sizeof(*p)); if(!p) fatal_exit("out of memory"); p->s = socket(serv_ip6?AF_INET6:AF_INET, SOCK_DGRAM, 0); if(p->s == -1) { #ifndef USE_WINSOCK fatal_exit("socket: %s", strerror(errno)); #else fatal_exit("socket: %s", wsa_strerror(WSAGetLastError())); #endif } fd_set_nonblock(p->s); memmove(&p->addr, from, from_len); p->addr_len = from_len; p->next = *proxies; *proxies = p; FD_SET(FD_SET_T p->s, rorig); if(p->s+1 > *max) *max = p->s+1; return p; }
dtls_connection_t * connection_find(dtls_connection_t * connList, const struct sockaddr_storage * addr, size_t addrLen) { dtls_connection_t * connP; connP = connList; while (connP != NULL) { if (sockaddr_cmp((struct sockaddr*) (&connP->addr),(struct sockaddr*) addr)) { return connP; } connP = connP->next; } return connP; }
/** * return: true if pending query matches the now event. */ static int pending_matches_current(struct replay_runtime* runtime, struct entry** entry, struct fake_pending **pend) { struct fake_pending* p; struct entry* e; if(!runtime->now || runtime->now->evt_type != repevt_back_query || !runtime->pending_list) return 0; /* see if any of the pending queries matches */ for(p = runtime->pending_list; p; p = p->next) { if(runtime->now->addrlen != 0 && sockaddr_cmp(&p->addr, p->addrlen, &runtime->now->addr, runtime->now->addrlen) != 0) continue; if((e=find_match(runtime->now->match, p->pkt, p->transport))) { *entry = e; *pend = p; return 1; } } return 0; }
/** Check the now moment answer check event */ static void answer_check_it(struct replay_runtime* runtime) { struct replay_answer* ans = runtime->answer_list, *prev = NULL; log_assert(runtime && runtime->now && runtime->now->evt_type == repevt_front_reply); while(ans) { enum transport_type tr = transport_tcp; if(ans->repinfo.c->type == comm_udp) tr = transport_udp; if((runtime->now->addrlen == 0 || sockaddr_cmp( &runtime->now->addr, runtime->now->addrlen, &ans->repinfo.addr, ans->repinfo.addrlen) == 0) && find_match(runtime->now->match, ans->pkt, ans->pkt_len, tr)) { log_info("testbound matched event entry from line %d", runtime->now->match->lineno); log_info("testbound: do STEP %d %s", runtime->now->time_step, repevt_string(runtime->now->evt_type)); if(prev) prev->next = ans->next; else runtime->answer_list = ans->next; if(!ans->next) runtime->answer_last = prev; delete_replay_answer(ans); return; } else { prev = ans; ans = ans->next; } } log_info("testbound: do STEP %d %s", runtime->now->time_step, repevt_string(runtime->now->evt_type)); fatal_exit("testbound: not matched"); }
static void server_recv_cb(EV_P_ ev_io *w, int revents) { server_ctx_t *server_ctx = (server_ctx_t *)w; struct sockaddr_storage src_addr; memset(&src_addr, 0, sizeof(struct sockaddr_storage)); buffer_t *buf = ss_malloc(sizeof(buffer_t)); balloc(buf, buf_size); socklen_t src_addr_len = sizeof(struct sockaddr_storage); unsigned int offset = 0; #ifdef MODULE_REDIR char control_buffer[64] = { 0 }; struct msghdr msg; memset(&msg, 0, sizeof(struct msghdr)); struct iovec iov[1]; struct sockaddr_storage dst_addr; memset(&dst_addr, 0, sizeof(struct sockaddr_storage)); msg.msg_name = &src_addr; msg.msg_namelen = src_addr_len; msg.msg_control = control_buffer; msg.msg_controllen = sizeof(control_buffer); iov[0].iov_base = buf->data; iov[0].iov_len = buf_size; msg.msg_iov = iov; msg.msg_iovlen = 1; buf->len = recvmsg(server_ctx->fd, &msg, 0); if (buf->len == -1) { ERROR("[udp] server_recvmsg"); goto CLEAN_UP; } else if (buf->len > packet_size) { if (verbose) { LOGI("[udp] UDP server_recv_recvmsg fragmentation"); } } if (get_dstaddr(&msg, &dst_addr)) { LOGE("[udp] unable to get dest addr"); goto CLEAN_UP; } src_addr_len = msg.msg_namelen; #else ssize_t r; r = recvfrom(server_ctx->fd, buf->data, buf_size, 0, (struct sockaddr *)&src_addr, &src_addr_len); if (r == -1) { // error on recv // simply drop that packet ERROR("[udp] server_recv_recvfrom"); goto CLEAN_UP; } else if (r > packet_size) { if (verbose) { LOGI("[udp] server_recv_recvfrom fragmentation"); } } buf->len = r; #endif if (verbose) { LOGI("[udp] server receive a packet"); } #ifdef MODULE_REMOTE tx += buf->len; int err = server_ctx->crypto->decrypt_all(buf, server_ctx->crypto->cipher, buf_size); if (err) { // drop the packet silently goto CLEAN_UP; } #endif #ifdef MODULE_LOCAL #if !defined(MODULE_TUNNEL) && !defined(MODULE_REDIR) #ifdef __ANDROID__ tx += buf->len; #endif uint8_t frag = *(uint8_t *)(buf->data + 2); offset += 3; #endif #endif /* * * SOCKS5 UDP Request * +----+------+------+----------+----------+----------+ * |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA | * +----+------+------+----------+----------+----------+ * | 2 | 1 | 1 | Variable | 2 | Variable | * +----+------+------+----------+----------+----------+ * * SOCKS5 UDP Response * +----+------+------+----------+----------+----------+ * |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA | * +----+------+------+----------+----------+----------+ * | 2 | 1 | 1 | Variable | 2 | Variable | * +----+------+------+----------+----------+----------+ * * shadowsocks UDP Request (before encrypted) * +------+----------+----------+----------+ * | ATYP | DST.ADDR | DST.PORT | DATA | * +------+----------+----------+----------+ * | 1 | Variable | 2 | Variable | * +------+----------+----------+----------+ * * shadowsocks UDP Response (before encrypted) * +------+----------+----------+----------+ * | ATYP | DST.ADDR | DST.PORT | DATA | * +------+----------+----------+----------+ * | 1 | Variable | 2 | Variable | * +------+----------+----------+----------+ * * shadowsocks UDP Request and Response (after encrypted) * +-------+--------------+ * | IV | PAYLOAD | * +-------+--------------+ * | Fixed | Variable | * +-------+--------------+ * */ #ifdef MODULE_REDIR char addr_header[512] = { 0 }; int addr_header_len = construct_udprelay_header(&dst_addr, addr_header); if (addr_header_len == 0) { LOGE("[udp] failed to parse tproxy addr"); goto CLEAN_UP; } // reconstruct the buffer brealloc(buf, buf->len + addr_header_len, buf_size); memmove(buf->data + addr_header_len, buf->data, buf->len); memcpy(buf->data, addr_header, addr_header_len); buf->len += addr_header_len; #elif MODULE_TUNNEL char addr_header[512] = { 0 }; char *host = server_ctx->tunnel_addr.host; char *port = server_ctx->tunnel_addr.port; uint16_t port_num = (uint16_t)atoi(port); uint16_t port_net_num = htons(port_num); int addr_header_len = 0; struct cork_ip ip; if (cork_ip_init(&ip, host) != -1) { if (ip.version == 4) { // send as IPv4 struct in_addr host_addr; memset(&host_addr, 0, sizeof(struct in_addr)); int host_len = sizeof(struct in_addr); if (dns_pton(AF_INET, host, &host_addr) == -1) { FATAL("IP parser error"); } addr_header[addr_header_len++] = 1; memcpy(addr_header + addr_header_len, &host_addr, host_len); addr_header_len += host_len; } else if (ip.version == 6) { // send as IPv6 struct in6_addr host_addr; memset(&host_addr, 0, sizeof(struct in6_addr)); int host_len = sizeof(struct in6_addr); if (dns_pton(AF_INET6, host, &host_addr) == -1) { FATAL("IP parser error"); } addr_header[addr_header_len++] = 4; memcpy(addr_header + addr_header_len, &host_addr, host_len); addr_header_len += host_len; } else { FATAL("IP parser error"); } } else { // send as domain int host_len = strlen(host); addr_header[addr_header_len++] = 3; addr_header[addr_header_len++] = host_len; memcpy(addr_header + addr_header_len, host, host_len); addr_header_len += host_len; } memcpy(addr_header + addr_header_len, &port_net_num, 2); addr_header_len += 2; // reconstruct the buffer brealloc(buf, buf->len + addr_header_len, buf_size); memmove(buf->data + addr_header_len, buf->data, buf->len); memcpy(buf->data, addr_header, addr_header_len); buf->len += addr_header_len; #else char host[257] = { 0 }; char port[64] = { 0 }; struct sockaddr_storage dst_addr; memset(&dst_addr, 0, sizeof(struct sockaddr_storage)); int addr_header_len = parse_udprelay_header(buf->data + offset, buf->len - offset, host, port, &dst_addr); if (addr_header_len == 0) { // error in parse header goto CLEAN_UP; } char *addr_header = buf->data + offset; #endif #ifdef MODULE_LOCAL char *key = hash_key(server_ctx->remote_addr->sa_family, &src_addr); #else char *key = hash_key(dst_addr.ss_family, &src_addr); #endif struct cache *conn_cache = server_ctx->conn_cache; remote_ctx_t *remote_ctx = NULL; cache_lookup(conn_cache, key, HASH_KEY_LEN, (void *)&remote_ctx); if (remote_ctx != NULL) { if (sockaddr_cmp(&src_addr, &remote_ctx->src_addr, sizeof(src_addr))) { remote_ctx = NULL; } } // reset the timer if (remote_ctx != NULL) { ev_timer_again(EV_A_ & remote_ctx->watcher); } if (remote_ctx == NULL) { if (verbose) { #ifdef MODULE_REDIR char src[SS_ADDRSTRLEN]; char dst[SS_ADDRSTRLEN]; strcpy(src, get_addr_str((struct sockaddr *)&src_addr)); strcpy(dst, get_addr_str((struct sockaddr *)&dst_addr)); LOGI("[udp] cache miss: %s <-> %s", dst, src); #else LOGI("[udp] cache miss: %s:%s <-> %s", host, port, get_addr_str((struct sockaddr *)&src_addr)); #endif } } else { if (verbose) { #ifdef MODULE_REDIR char src[SS_ADDRSTRLEN]; char dst[SS_ADDRSTRLEN]; strcpy(src, get_addr_str((struct sockaddr *)&src_addr)); strcpy(dst, get_addr_str((struct sockaddr *)&dst_addr)); LOGI("[udp] cache hit: %s <-> %s", dst, src); #else LOGI("[udp] cache hit: %s:%s <-> %s", host, port, get_addr_str((struct sockaddr *)&src_addr)); #endif } } #ifdef MODULE_LOCAL #if !defined(MODULE_TUNNEL) && !defined(MODULE_REDIR) if (frag) { LOGE("[udp] drop a message since frag is not 0, but %d", frag); goto CLEAN_UP; } #endif const struct sockaddr *remote_addr = server_ctx->remote_addr; const int remote_addr_len = server_ctx->remote_addr_len; if (remote_ctx == NULL) { // Bind to any port int remotefd = create_remote_socket(remote_addr->sa_family == AF_INET6); if (remotefd < 0) { ERROR("[udp] udprelay bind() error"); goto CLEAN_UP; } setnonblocking(remotefd); #ifdef SO_NOSIGPIPE set_nosigpipe(remotefd); #endif #ifdef IP_TOS // Set QoS flag int tos = 46; setsockopt(remotefd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); #endif #ifdef SET_INTERFACE if (server_ctx->iface) { if (setinterface(remotefd, server_ctx->iface) == -1) ERROR("setinterface"); } #endif #ifdef __ANDROID__ if (vpn) { if (protect_socket(remotefd) == -1) { ERROR("protect_socket"); close(remotefd); goto CLEAN_UP; } } #endif // Init remote_ctx remote_ctx = new_remote(remotefd, server_ctx); remote_ctx->src_addr = src_addr; remote_ctx->af = remote_addr->sa_family; remote_ctx->addr_header_len = addr_header_len; memcpy(remote_ctx->addr_header, addr_header, addr_header_len); // Add to conn cache cache_insert(conn_cache, key, HASH_KEY_LEN, (void *)remote_ctx); // Start remote io ev_io_start(EV_A_ & remote_ctx->io); ev_timer_start(EV_A_ & remote_ctx->watcher); } if (offset > 0) { buf->len -= offset; memmove(buf->data, buf->data + offset, buf->len); } int err = server_ctx->crypto->encrypt_all(buf, server_ctx->crypto->cipher, buf_size); if (err) { // drop the packet silently goto CLEAN_UP; } if (buf->len > packet_size) { if (verbose) { LOGI("[udp] server_recv_sendto fragmentation"); } } int s = sendto(remote_ctx->fd, buf->data, buf->len, 0, remote_addr, remote_addr_len); if (s == -1) { ERROR("[udp] server_recv_sendto"); } #else int cache_hit = 0; int need_query = 0; if (buf->len - addr_header_len > packet_size) { if (verbose) { LOGI("[udp] server_recv_sendto fragmentation"); } } if (remote_ctx != NULL) { cache_hit = 1; // detect destination mismatch if (remote_ctx->addr_header_len != addr_header_len || memcmp(addr_header, remote_ctx->addr_header, addr_header_len) != 0) { if (dst_addr.ss_family != AF_INET && dst_addr.ss_family != AF_INET6) { need_query = 1; } } else { memcpy(&dst_addr, &remote_ctx->dst_addr, sizeof(struct sockaddr_storage)); } } else { if (dst_addr.ss_family == AF_INET || dst_addr.ss_family == AF_INET6) { int remotefd = create_remote_socket(dst_addr.ss_family == AF_INET6); if (remotefd != -1) { setnonblocking(remotefd); #ifdef SO_BROADCAST set_broadcast(remotefd); #endif #ifdef SO_NOSIGPIPE set_nosigpipe(remotefd); #endif #ifdef IP_TOS // Set QoS flag int tos = 46; setsockopt(remotefd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); #endif #ifdef SET_INTERFACE if (server_ctx->iface) { if (setinterface(remotefd, server_ctx->iface) == -1) ERROR("setinterface"); } #endif remote_ctx = new_remote(remotefd, server_ctx); remote_ctx->src_addr = src_addr; remote_ctx->server_ctx = server_ctx; remote_ctx->addr_header_len = addr_header_len; memcpy(remote_ctx->addr_header, addr_header, addr_header_len); memcpy(&remote_ctx->dst_addr, &dst_addr, sizeof(struct sockaddr_storage)); } else { ERROR("[udp] bind() error"); goto CLEAN_UP; } } } if (remote_ctx != NULL && !need_query) { size_t addr_len = get_sockaddr_len((struct sockaddr *)&dst_addr); int s = sendto(remote_ctx->fd, buf->data + addr_header_len, buf->len - addr_header_len, 0, (struct sockaddr *)&dst_addr, addr_len); if (s == -1) { ERROR("[udp] sendto_remote"); if (!cache_hit) { close_and_free_remote(EV_A_ remote_ctx); } } else { if (!cache_hit) { // Add to conn cache remote_ctx->af = dst_addr.ss_family; char *key = hash_key(remote_ctx->af, &remote_ctx->src_addr); cache_insert(server_ctx->conn_cache, key, HASH_KEY_LEN, (void *)remote_ctx); ev_io_start(EV_A_ & remote_ctx->io); ev_timer_start(EV_A_ & remote_ctx->watcher); } } } else { struct addrinfo hints; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; struct query_ctx *query_ctx = new_query_ctx(buf->data + addr_header_len, buf->len - addr_header_len); query_ctx->server_ctx = server_ctx; query_ctx->addr_header_len = addr_header_len; query_ctx->src_addr = src_addr; memcpy(query_ctx->addr_header, addr_header, addr_header_len); if (need_query) { query_ctx->remote_ctx = remote_ctx; } struct ResolvQuery *query = resolv_query(host, query_resolve_cb, NULL, query_ctx, htons(atoi(port))); if (query == NULL) { ERROR("[udp] unable to create DNS query"); close_and_free_query(EV_A_ query_ctx); goto CLEAN_UP; } query_ctx->query = query; } #endif CLEAN_UP: bfree(buf); ss_free(buf); }
struct serviced_query* outnet_serviced_query(struct outside_network* outnet, uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec, int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream), struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, size_t zonelen, comm_point_callback_t* callback, void* callback_arg, sldns_buffer* ATTR_UNUSED(buff)) { struct replay_runtime* runtime = (struct replay_runtime*)outnet->base; struct fake_pending* pend = (struct fake_pending*)calloc(1, sizeof(struct fake_pending)); char z[256]; log_assert(pend); log_nametypeclass(VERB_OPS, "pending serviced query", qname, qtype, qclass); dname_str(zone, z); verbose(VERB_OPS, "pending serviced query zone %s flags%s%s%s%s", z, (flags&BIT_RD)?" RD":"", (flags&BIT_CD)?" CD":"", (flags&~(BIT_RD|BIT_CD))?" MORE":"", (dnssec)?" DO":""); /* create packet with EDNS */ pend->buffer = sldns_buffer_new(512); log_assert(pend->buffer); sldns_buffer_write_u16(pend->buffer, 0); /* id */ sldns_buffer_write_u16(pend->buffer, flags); sldns_buffer_write_u16(pend->buffer, 1); /* qdcount */ sldns_buffer_write_u16(pend->buffer, 0); /* ancount */ sldns_buffer_write_u16(pend->buffer, 0); /* nscount */ sldns_buffer_write_u16(pend->buffer, 0); /* arcount */ sldns_buffer_write(pend->buffer, qname, qnamelen); sldns_buffer_write_u16(pend->buffer, qtype); sldns_buffer_write_u16(pend->buffer, qclass); sldns_buffer_flip(pend->buffer); if(1) { /* add edns */ struct edns_data edns; edns.edns_present = 1; edns.ext_rcode = 0; edns.edns_version = EDNS_ADVERTISED_VERSION; edns.udp_size = EDNS_ADVERTISED_SIZE; edns.bits = 0; if(dnssec) edns.bits = EDNS_DO; attach_edns_record(pend->buffer, &edns); } memcpy(&pend->addr, addr, addrlen); pend->addrlen = addrlen; pend->zone = memdup(zone, zonelen); pend->zonelen = zonelen; pend->qtype = (int)qtype; log_assert(pend->zone); pend->callback = callback; pend->cb_arg = callback_arg; pend->timeout = UDP_AUTH_QUERY_TIMEOUT; pend->transport = transport_udp; /* pretend UDP */ pend->pkt = NULL; pend->runtime = runtime; pend->serviced = 1; pend->pkt_len = sldns_buffer_limit(pend->buffer); pend->pkt = memdup(sldns_buffer_begin(pend->buffer), pend->pkt_len); if(!pend->pkt) fatal_exit("out of memory"); /*log_pkt("pending serviced query: ", pend->pkt, pend->pkt_len);*/ /* see if it matches the current moment */ if(runtime->now && runtime->now->evt_type == repevt_back_query && (runtime->now->addrlen == 0 || sockaddr_cmp( &runtime->now->addr, runtime->now->addrlen, &pend->addr, pend->addrlen) == 0) && find_match(runtime->now->match, pend->pkt, pend->pkt_len, pend->transport)) { log_info("testbound: matched pending to event. " "advance time between events."); log_info("testbound: do STEP %d %s", runtime->now->time_step, repevt_string(runtime->now->evt_type)); advance_moment(runtime); /* still create the pending, because we need it to callback */ } log_info("testbound: created fake pending"); /* add to list */ pend->next = runtime->pending_list; runtime->pending_list = pend; return (struct serviced_query*)pend; }
/*! Run all scheduled tests for given parameters. */ int main(int argc, char *argv[]) { plan(19); // Test 1: Allocate new config const char *config_fn = "rc:/sample_conf"; conf_t *conf = conf_new(strdup(config_fn)); ok(conf != 0, "config_new()"); // Test 2: Parse config int ret = conf_parse_str(conf, sample_conf_rc); is_int(0, ret, "parsing configuration file %s", config_fn); if (ret != 0) { skip_block(19, "Parse err"); goto skip_all; } // Test 3: Test server version (0-level depth) is_string("Infinitesimal", conf->version, "server version loaded ok"); // Test 4: Test interfaces (1-level depth) ok(!EMPTY_LIST(conf->ifaces), "configured interfaces exist"); // Test 5,6: Interfaces content (2-level depth) struct node *n = HEAD(conf->ifaces); conf_iface_t *iface = (conf_iface_t*)n; struct sockaddr_storage addr_ref; sockaddr_set(&addr_ref, AF_INET, "10.10.1.1", 53531); is_int(0, sockaddr_cmp(&iface->addr, &addr_ref), "interface0 address check"); n = n->next; iface = (conf_iface_t*)n; sockaddr_set(&addr_ref, AF_INET6, "::0", 53); is_int(0, sockaddr_cmp(&iface->addr, &addr_ref), "interface1 address check"); // Test 9,10: Check server key if (EMPTY_LIST(conf->keys)) { ok(0, "TSIG key algorithm check - NO KEY FOUND"); ok(0, "TSIG key secret check - NO KEY FOUND"); } else { knot_tsig_key_t *k = &((conf_key_t *)HEAD(conf->keys))->k; uint8_t decoded_secret[] = { 0x5a }; ok(k->algorithm == KNOT_TSIG_ALG_HMAC_MD5, "TSIG key algorithm check"); ok(k->secret.size == sizeof(decoded_secret) && memcmp(k->secret.data, decoded_secret, sizeof(decoded_secret)) == 0, "TSIG key secret check"); } // Test 11,12,13,14,15,16,17,18: Check logging facilities ok(list_size(&conf->logs) == 4, "log facilites count check"); n = HEAD(conf->logs); ok(!EMPTY_LIST(conf->logs), "log facilities not empty"); conf_log_t *log = (conf_log_t*)n; node_t *nm = HEAD(log->map); conf_log_map_t *m = (conf_log_map_t*)nm; ok(log->type == LOGT_SYSLOG, "log0 is syslog"); if (EMPTY_LIST(log->map)) { skip_block(5, "Empty list"); } else { ok(m->source == LOG_ANY, "syslog first rule is ANY"); int mask = LOG_UPTO(LOG_NOTICE); ok(m->prios == mask, "syslog mask is equal"); nm = nm->next; m = (conf_log_map_t*)nm; ok(m != 0, "syslog has more than 1 rule"); if (m == 0) { skip_block(2, "No mapping"); } else { ok(m->source == LOG_ZONE, "syslog next rule is for zone"); ok(m->prios == LOG_UPTO(LOG_INFO), "rule for zone is: info level"); } } // Test 19,20: File facility checks n = n->next; log = (conf_log_t*)n; ok(n != 0, "log has next facility"); if (n == 0) { skip("No mapping"); } else { is_string("/var/log/knot/server.err", log->file, "log file matches"); } // Test 21: Load key dname const char *sample_str = "key0.example.net"; knot_dname_t *sample = knot_dname_from_str_alloc(sample_str); if (list_size(&conf->keys) > 0) { knot_tsig_key_t *k = &((conf_key_t *)HEAD(conf->keys))->k; ok(knot_dname_cmp(sample, k->name) == 0, "TSIG key dname check"); } else { ok(0, "TSIG key dname check - NO KEY FOUND"); } knot_dname_free(&sample, NULL); skip_all: // Deallocating config conf_free(conf); return 0; }