Пример #1
0
/* 
** nread, addr/nil, port/nil, err = socket.recvfromb(fd, buffer)
**
** won't block even if the fd is working in blocking mode.
*/
static int lsocket_recvfromb(lua_State *L) {
	int fd = luaL_checkint(L, 1);
	Buffer *buf = buffer_lcheck(L, 2);
	char addr[MAX_ADDRSTRLEN];
	int port;
	size_t navaiable = 0, nread = 0;
	int err = 0;
	
	err = os_getnread(fd, &navaiable);
	if (navaiable > 0) {
		uint8 *p = buffer_grow(buf, (size_t)navaiable);
		err = socket_recvfrom(fd, p, navaiable, 0, addr, &port, &nread);
		
		if (nread < navaiable)
			buffer_pop(buf, navaiable - nread);
	}
	
	if (err != 0 || navaiable == 0) {
		lua_pushinteger(L, 0);
		lua_pushnil(L);
		lua_pushnil(L);
		lua_pushinteger(L, err);
	} else {
		lua_pushinteger(L, nread);
		lua_pushstring(L, addr);
		lua_pushinteger(L, port);
		lua_pushinteger(L, 0);
	}
		
	return 4;
}
Пример #2
0
/*-------------------------------------------------------------------------*\
* Receives data and sender from a UDP socket
\*-------------------------------------------------------------------------*/
static int meth_receivefrom(lua_State *L)
{
    p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1);
    char buffer[UDP_DATAGRAMSIZE];
    size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer));
    int err;
    p_timeout tm = &udp->tm;
    struct sockaddr_storage addr;
    socklen_t addr_len = sizeof(addr);
    char addrstr[INET6_ADDRSTRLEN];
    char portstr[6];
    timeout_markstart(tm);
    count = MIN(count, sizeof(buffer));
    err = socket_recvfrom(&udp->sock, buffer, count, &got, (SA *) &addr, 
            &addr_len, tm);
    /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
    if (err == IO_CLOSED)
        err = IO_DONE;
    if (err != IO_DONE) {
        lua_pushnil(L);
        lua_pushstring(L, udp_strerror(err));
        return 2;
    }
    err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr, 
        INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV);
	if (err) {
        lua_pushnil(L);
        lua_pushstring(L, gai_strerror(err));
        return 2;
    }
    lua_pushlstring(L, buffer, got);
    lua_pushstring(L, addrstr);
    lua_pushinteger(L, (int) strtol(portstr, (char **) NULL, 10));
    return 3;
}
Пример #3
0
/* 
** str/nil, addr/nil, port/nil, err = socket.recvfrom(fd)
**
** won't block even if the fd is working in blocking mode.
*/
static int lsocket_recvfrom(lua_State *L) {
	int fd = luaL_checkint(L, 1);
	char addr[MAX_ADDRSTRLEN];
	int port;
	Buffer buf;
	size_t navaiable = 0;
	int err = 0;
	
	buffer_init(&buf, 0);
	err = os_getnread(fd, &navaiable);
	if (navaiable > 0) {
		uint8 *p = buffer_grow(&buf, (size_t)navaiable);
		size_t nread = 0;
		err = socket_recvfrom(fd, p, navaiable, 0, addr, &port, &nread);
		
		if (nread < navaiable)
			buffer_pop(&buf, navaiable - nread);
	}
	
	if (err != 0 || navaiable == 0) {
		lua_pushnil(L);
		lua_pushnil(L);
		lua_pushnil(L);
		lua_pushinteger(L, err);
	} else {
		lua_pushlstring(L, (const char*)buf.data, buf.datasiz);
		lua_pushstring(L, addr);
		lua_pushinteger(L, port);
		lua_pushinteger(L, 0);
	}
	buffer_finalize(&buf);
		
	return 4;
}
Пример #4
0
static void udp_listener_incoming(int fd, void *p, uintptr_t x) {
	struct udp_listener_callback *cb = p;
	int len;
	char buf[0x10000];
	char addr[64];
	str str;
	struct udp_listener *ul;
	socket_t *listener;
	endpoint_t sin;

	str.s = buf;
	ul = cb->ul;
	listener = &ul->sock;

	for (;;) {
		len = socket_recvfrom(listener, buf, sizeof(buf)-1, &sin);
		if (len < 0) {
			if (errno == EINTR)
				continue;
			if (errno != EWOULDBLOCK && errno != EAGAIN)
				ilog(LOG_WARNING, "Error reading from UDP socket");
			return;
		}

		buf[len] = '\0';
		endpoint_print(&sin, addr, sizeof(addr));

		str.len = len;
		cb->func(cb->p, &str, &sin, addr, ul);
	}
}
Пример #5
0
int udp_nb_recvfrom(int s,
		    KX_MSG *msg,
		    struct sockaddr *from,
		    int *fromlen)
{
	char	*buf = (char *)&(msg->m_data[msg->m_curlen]);
	int	len = msg->m_maxlen - msg->m_curlen;
	int	attempt=0;
	int	cc;

try_again:
	attempt++;
	*fromlen = sizeof(struct sockaddr);
#ifdef macintosh
	cc = socket_recvfrom(s, buf, len, 0, from, (void *)fromlen);
#else /* !macintosh */
	cc = recvfrom(s, buf, len, 0, from, (void *)fromlen);

	if ((cc == -1) && (errno == EAGAIN))
		goto try_again;
#endif /* macintosh */

	if (cc > 0)
		msg->m_curlen += cc;

	return cc;
}
Пример #6
0
int test_udp() {
    int fd = socket_new(SOCK_DGRAM);  
    fd =socket_bind(fd, NULL, 9000);
    
    printf("socket fd: %d\n", fd);

    //socket_nonblock(connfd);

    //socket_message msg;
    char cip[16] = {0};
    int port = 0;
    char* msg = (char*)socket_recvfrom(fd, cip, &port);

    printf("body=%s\n", msg);

    socket_close(fd);
    free(msg);

    return 0;
}
Пример #7
0
/*
 * Read a received packet into buffer buf (which is of maximum length len);
 * store calling ip and port as well. Call available() to make sure data is
 * ready first.
 * NOTE: I don't believe len is ever checked in implementation of recvfrom(),
 *       so it's easy to overflow buffer. so we check and truncate.
 * Returns number of bytes read, or negative number of bytes we would have
 * needed if we truncated.
 */
int udp_read_packet (udp_t *u, uint8_t *buf, unsigned len,
                     uint8_t *ip, unsigned *port)
{
    int nbytes = udp_available (u) - 8;     /* skip UDP header */
    if (nbytes < 0) {
        /* No real data here. */
        return 0;
    }

    if (nbytes > (int)len) {
        /* Packet is too large - truncate.
         * HACK: hand-parse the UDP packet using TCP recv method. */
        uint8_t tmpBuf[8];
        int i;

        /* Read 8 header bytes and get IP and port from it. */
        socket_recv (u->sock, tmpBuf, 8);
        if (ip != 0) {
            ip[0] = tmpBuf[0];
            ip[1] = tmpBuf[1];
            ip[2] = tmpBuf[2];
            ip[3] = tmpBuf[3];
        }
        if (port != 0)
            *port = (tmpBuf[4] << 8) + tmpBuf[5];

        /* Now copy first (len) bytes into buf. */
        for (i=0; i<(int)len; i++) {
            socket_recv (u->sock, tmpBuf, 1);
            buf[i] = tmpBuf[0];
        }

        /* And just read the rest byte by byte and throw it away. */
        while (udp_available (u)) {
            socket_recv (u->sock, tmpBuf, 1);
        }
        return -nbytes;
    }
    return socket_recvfrom (u->sock, buf, len, ip, port);
}
Пример #8
0
Файл: udp.c Проект: leonlee/tome
/*-------------------------------------------------------------------------*\
* Receives data and sender from a UDP socket
\*-------------------------------------------------------------------------*/
static int meth_receivefrom(lua_State *L) {
    p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1);
    struct sockaddr_in addr;
    socklen_t addr_len = sizeof(addr);
    char buffer[UDP_DATAGRAMSIZE];
    size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer));
    int err;
    p_timeout tm = &udp->tm;
    timeout_markstart(tm);
    count = MIN(count, sizeof(buffer));
    err = socket_recvfrom(&udp->sock, buffer, count, &got, 
            (SA *) &addr, &addr_len, tm);
    if (err == IO_DONE) {
        lua_pushlstring(L, buffer, got);
        lua_pushstring(L, inet_ntoa(addr.sin_addr));
        lua_pushnumber(L, ntohs(addr.sin_port));
        return 3;
    } else {
        lua_pushnil(L);
        lua_pushstring(L, udp_strerror(err));
        return 2;
    }
}
Пример #9
0
nsapi_size_or_error_t NanostackInterface::socket_recv(void *handle, void *data, nsapi_size_t size)
{
    return socket_recvfrom(handle, NULL, data, size);
}
Пример #10
0
/*
  handle recv events on a nbt dgram socket
*/
static void dgm_socket_recv(struct nbt_dgram_socket *dgmsock)
{
	TALLOC_CTX *tmp_ctx = talloc_new(dgmsock);
	NTSTATUS status;
	struct socket_address *src;
	DATA_BLOB blob;
	size_t nread, dsize;
	struct nbt_dgram_packet *packet;
	const char *mailslot_name;
	enum ndr_err_code ndr_err;

	status = socket_pending(dgmsock->sock, &dsize);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(tmp_ctx);
		return;
	}

	blob = data_blob_talloc(tmp_ctx, NULL, dsize);
	if ((dsize != 0) && (blob.data == NULL)) {
		talloc_free(tmp_ctx);
		return;
	}

	status = socket_recvfrom(dgmsock->sock, blob.data, blob.length, &nread,
				 tmp_ctx, &src);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(tmp_ctx);
		return;
	}
	blob.length = nread;

	DEBUG(5,("Received dgram packet of length %d from %s:%d\n", 
		 (int)blob.length, src->addr, src->port));

	packet = talloc(tmp_ctx, struct nbt_dgram_packet);
	if (packet == NULL) {
		talloc_free(tmp_ctx);
		return;
	}

	/* parse the request */
	ndr_err = ndr_pull_struct_blob(&blob, packet, packet,
				      (ndr_pull_flags_fn_t)ndr_pull_nbt_dgram_packet);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(2,("Failed to parse incoming NBT DGRAM packet - %s\n",
			 nt_errstr(status)));
		talloc_free(tmp_ctx);
		return;
	}

	/* if this is a mailslot message, then see if we can dispatch it to a handler */
	mailslot_name = dgram_mailslot_name(packet);
	if (mailslot_name) {
		struct dgram_mailslot_handler *dgmslot;
		dgmslot = dgram_mailslot_find(dgmsock, mailslot_name);
		if (dgmslot) {
			dgmslot->handler(dgmslot, packet, src);
		} else {
			DEBUG(2,("No mailslot handler for '%s'\n", mailslot_name));
		}
	} else {
		/* dispatch if there is a general handler */
		if (dgmsock->incoming.handler) {
			dgmsock->incoming.handler(dgmsock, packet, src);
		}
	}

	talloc_free(tmp_ctx);
}
Пример #11
0
/**
  basic testing of udp routines
*/
static bool test_udp(struct torture_context *tctx)
{
	struct socket_context *sock1, *sock2;
	NTSTATUS status;
	struct socket_address *srv_addr, *from_addr, *localhost;
	size_t size = 100 + (random() % 100);
	DATA_BLOB blob, blob2;
	size_t sent, nread;
	TALLOC_CTX *mem_ctx = tctx;
	struct interface *ifaces;

	load_interfaces(tctx, lp_interfaces(tctx->lp_ctx), &ifaces);

	status = socket_create("ip", SOCKET_TYPE_DGRAM, &sock1, 0);
	torture_assert_ntstatus_ok(tctx, status, "creating DGRAM IP socket 1");
	talloc_steal(mem_ctx, sock1);

	status = socket_create("ip", SOCKET_TYPE_DGRAM, &sock2, 0);
	torture_assert_ntstatus_ok(tctx, status, "creating DGRAM IP socket 1");
	talloc_steal(mem_ctx, sock2);

	localhost = socket_address_from_strings(sock1, sock1->backend_name, 
						iface_best_ip(ifaces, "127.0.0.1"), 0);

	torture_assert(tctx, localhost, "Localhost not found");

	status = socket_listen(sock1, localhost, 0, 0);
	torture_assert_ntstatus_ok(tctx, status, "listen on socket 1");

	srv_addr = socket_get_my_addr(sock1, mem_ctx);
	torture_assert(tctx, srv_addr != NULL && 
		       strcmp(srv_addr->addr, iface_best_ip(ifaces, "127.0.0.1")) == 0,
				   talloc_asprintf(tctx, 
		"Expected server address of %s but got %s",
		      iface_best_ip(ifaces, "127.0.0.1"), srv_addr ? srv_addr->addr : NULL));

	torture_comment(tctx, "server port is %d\n", srv_addr->port);

	blob  = data_blob_talloc(mem_ctx, NULL, size);
	blob2 = data_blob_talloc(mem_ctx, NULL, size);
	generate_random_buffer(blob.data, blob.length);

	sent = size;
	status = socket_sendto(sock2, &blob, &sent, srv_addr);
	torture_assert_ntstatus_ok(tctx, status, "sendto() on socket 2");

	status = socket_recvfrom(sock1, blob2.data, size, &nread, 
				 sock1, &from_addr);
	torture_assert_ntstatus_ok(tctx, status, "recvfrom() on socket 1");

	torture_assert_str_equal(tctx, from_addr->addr, srv_addr->addr, 
							 "different address");

	torture_assert_int_equal(tctx, nread, size, "Unexpected recvfrom size");

	torture_assert_mem_equal(tctx, blob2.data, blob.data, size,
		"Bad data in recvfrom");

	generate_random_buffer(blob.data, blob.length);
	status = socket_sendto(sock1, &blob, &sent, from_addr);
	torture_assert_ntstatus_ok(tctx, status, "sendto() on socket 1");

	status = socket_recvfrom(sock2, blob2.data, size, &nread, 
				 sock2, &from_addr);
	torture_assert_ntstatus_ok(tctx, status, "recvfrom() on socket 2");
	torture_assert_str_equal(tctx, from_addr->addr, srv_addr->addr, 
							 "Unexpected recvfrom addr");
	
	torture_assert_int_equal(tctx, nread, size, "Unexpected recvfrom size");

	torture_assert_int_equal(tctx, from_addr->port, srv_addr->port, 
				   "Unexpected recvfrom port");

	torture_assert_mem_equal(tctx, blob2.data, blob.data, size,
		"Bad data in recvfrom");

	talloc_free(sock1);
	talloc_free(sock2);
	return true;
}
Пример #12
0
static int socket_dev_ioctl(dev_cookie cookie, int op, void *buf, size_t len)
{
	socket_dev *s = (socket_dev *)cookie;
	_socket_api_args_t args;
	int err;

	// copy the args over from user space
	err = user_memcpy(&args, buf, min(sizeof(args), len));
	if(err < 0)
		return err;

	if(s->id < 0) {
		switch(op) {
			case _SOCKET_API_CREATE:
				err = s->id = socket_create(args.u.create.type, args.u.create.flags);
				break;
			case _SOCKET_API_ASSOCIATE_SOCKET:
				s->id = args.u.associate.id;
				err = NO_ERROR;
				break;
			default:
				err = ERR_INVALID_ARGS;
		}
	} else {
		switch(op) {
			case _SOCKET_API_BIND:
				err = socket_bind(s->id, args.u.bind.saddr);
				break;
			case _SOCKET_API_CONNECT:
				err = socket_connect(s->id, args.u.connect.saddr);
				break;
			case _SOCKET_API_LISTEN:
				err = socket_listen(s->id);
				break;
			case _SOCKET_API_ACCEPT: {
				// this one is a little tricky, we have a new socket we need to associate with a file descriptor
				sock_id id;
				int fd;
				_socket_api_args_t new_args;
				char socket_dev_path[SYS_MAX_PATH_LEN];

				id = socket_accept(s->id, args.u.accept.saddr);
				if(id < 0) {
					err = id;
					break;
				}

				// we have the new id, open a new file descriptor in user space
				strcpy(socket_dev_path, "/dev/net/socket");
				fd = vfs_open(socket_dev_path, 0, false);
				if(fd < 0) {
					socket_close(id);
					err = fd;
					break;
				}

				// now do a special call on this file descriptor that associates it with this socket
				new_args.u.associate.id = id;
				err = vfs_ioctl(fd, _SOCKET_API_ASSOCIATE_SOCKET, &new_args, sizeof(new_args), false);
				if(err < 0) {
					socket_close(id);
					break;
				}

				err = fd;
				break;
			}
			case _SOCKET_API_RECVFROM:
				err = socket_recvfrom(s->id, args.u.transfer.buf, args.u.transfer.len, args.u.transfer.saddr);
				break;
			case _SOCKET_API_RECVFROM_ETC:
				err = socket_recvfrom_etc(s->id, args.u.transfer.buf, args.u.transfer.len, args.u.transfer.saddr, args.u.transfer.flags, args.u.transfer.timeout);
				break;
			case _SOCKET_API_SENDTO:
				err = socket_sendto(s->id, args.u.transfer.buf, args.u.transfer.len, args.u.transfer.saddr);
				break;
			default:
				err = ERR_INVALID_ARGS;
		}
	}

	return err;
}
Пример #13
0
/*
 * recvfrom() a UDP socket
 */
void
sorecvfrom(struct socket *so)
{
        SockAddress  addr;

	DEBUG_CALL("sorecvfrom");
	DEBUG_ARG("so = %lx", (long)so);

	if (so->so_type == IPPROTO_ICMP) {   /* This is a "ping" reply */
	  char buff[256];
	  int len;

	  len = socket_recvfrom(so->s, buff, 256, &addr);
	  /* XXX Check if reply is "correct"? */

	  if(len == -1 || len == 0) {
	    u_char code=ICMP_UNREACH_PORT;

	    if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
	    else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;

	    DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n",
			errno,errno_str));
	    icmp_error(so->so_m, ICMP_UNREACH,code, 0,errno_str);
	  } else {
	    icmp_reflect(so->so_m);
	    so->so_m = 0; /* Don't mbuf_free() it again! */
	  }
	  /* No need for this socket anymore, udp_detach it */
	  udp_detach(so);
	} else {                            	/* A "normal" UDP packet */
	  struct mbuf *m;
          int len;
		  int n;

	  if (!(m = m_get())) return;
	  m->m_data += IF_MAXLINKHDR;

	  /*
	   * XXX Shouldn't FIONREAD packets destined for port 53,
	   * but I don't know the max packet size for DNS lookups
	   */
	  len = M_FREEROOM(m);
	  /* if (so->so_fport != htons(53)) { */
	  n = socket_can_read(so->s);

	  if (n > len) {
	    n = (m->m_data - m->m_dat) + m->m_len + n + 1;
	    m_inc(m, n);
	    len = M_FREEROOM(m);
	  }
	  /* } */

	  m->m_len = socket_recvfrom(so->s, m->m_data, len, &addr);
	  DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n",
		      m->m_len, errno,errno_str));
	  if(m->m_len<0) {
	    u_char code=ICMP_UNREACH_PORT;

	    if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
	    else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;

	    DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code));
	    icmp_error(so->so_m, ICMP_UNREACH,code, 0,errno_str);
	    m_free(m);
	  } else {
	  /*
	   * Hack: domain name lookup will be used the most for UDP,
	   * and since they'll only be used once there's no need
	   * for the 4 minute (or whatever) timeout... So we time them
	   * out much quicker (10 seconds  for now...)
	   */
	    if (so->so_expire) {
	      if (so->so_faddr_port == 53)
		so->so_expire = curtime + SO_EXPIREFAST;
	      else
		so->so_expire = curtime + SO_EXPIRE;
	    }

	    /*		if (m->m_len == len) {
	     *			m_inc(m, MINCSIZE);
	     *			m->m_len = 0;
	     *		}
	     */

	    /*
	     * If this packet was destined for CTL_ADDR,
	     * make it look like that's where it came from, done by udp_output
	     */
	    udp_output_(so, m, &addr);
	  } /* rx error */
	} /* if ping packet */
}
Пример #14
0
/*
  handle fd recv events on a KDC socket
*/
static void kdc_recv_handler(struct kdc_socket *kdc_socket)
{
	NTSTATUS status;
	TALLOC_CTX *tmp_ctx = talloc_new(kdc_socket);
	DATA_BLOB blob;
	struct kdc_reply *rep;
	DATA_BLOB reply;
	size_t nread, dsize;
	struct socket_address *src;
	struct socket_address *my_addr;
	int ret;

	status = socket_pending(kdc_socket->sock, &dsize);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(tmp_ctx);
		return;
	}

	blob = data_blob_talloc(tmp_ctx, NULL, dsize);
	if (blob.data == NULL) {
		/* hope this is a temporary low memory condition */
		talloc_free(tmp_ctx);
		return;
	}

	status = socket_recvfrom(kdc_socket->sock, blob.data, blob.length, &nread,
				 tmp_ctx, &src);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(tmp_ctx);
		return;
	}
	blob.length = nread;
	
	DEBUG(10,("Received krb5 UDP packet of length %lu from %s:%u\n", 
		 (long)blob.length, src->addr, (uint16_t)src->port));
	
	my_addr = socket_get_my_addr(kdc_socket->sock, tmp_ctx);
	if (!my_addr) {
		talloc_free(tmp_ctx);
		return;
	}


	/* Call krb5 */
	ret = kdc_socket->process(kdc_socket->kdc, 
				  tmp_ctx, 
				  &blob,  
				  &reply,
				  src, my_addr,
				  1 /* Datagram */);
	if (!ret) {
		talloc_free(tmp_ctx);
		return;
	}

	/* queue a pending reply */
	rep = talloc(kdc_socket, struct kdc_reply);
	if (rep == NULL) {
		talloc_free(tmp_ctx);
		return;
	}
	rep->dest         = talloc_steal(rep, src);
	rep->packet       = reply;
	talloc_steal(rep, reply.data);

	if (rep->packet.data == NULL) {
		talloc_free(rep);
		talloc_free(tmp_ctx);
		return;
	}

	DLIST_ADD_END(kdc_socket->send_queue, rep, struct kdc_reply *);
	EVENT_FD_WRITEABLE(kdc_socket->fde);
	talloc_free(tmp_ctx);
}
Пример #15
0
/* If any UDP sockets select true for reading, process them. */
static void read_udp_packets(ares_channel channel, fd_set *read_fds,
                             ares_socket_t read_fd, struct timeval *now)
{
  struct server_state *server;
  int i;
  ares_ssize_t count;
  unsigned char buf[MAXENDSSZ + 1];
#ifdef HAVE_RECVFROM
  ares_socklen_t fromlen;
  union {
    struct sockaddr     sa;
    struct sockaddr_in  sa4;
    struct sockaddr_in6 sa6;
  } from;
#endif

  if(!read_fds && (read_fd == ARES_SOCKET_BAD))
    /* no possible action */
    return;

  for (i = 0; i < channel->nservers; i++)
    {
      /* Make sure the server has a socket and is selected in read_fds. */
      server = &channel->servers[i];

      if (server->udp_socket == ARES_SOCKET_BAD || server->is_broken)
        continue;

      if(read_fds) {
        if(!(FD_ISSET(server->udp_socket, read_fds)))
          continue;
      }
      else {
        if(server->udp_socket != read_fd)
          continue;
      }

      if(read_fds)
        /* If there's an error and we close this socket, then open
         * another with the same fd to talk to another server, then we
         * don't want to think that it was the new socket that was
         * ready. This is not disastrous, but is likely to result in
         * extra system calls and confusion. */
        FD_CLR(server->udp_socket, read_fds);

      /* To reduce event loop overhead, read and process as many
       * packets as we can. */
      do {
        if (server->udp_socket == ARES_SOCKET_BAD)
          count = 0;

        else {
          if (server->addr.family == AF_INET)
            fromlen = sizeof(from.sa4);
          else
            fromlen = sizeof(from.sa6);
          count = socket_recvfrom(channel, server->udp_socket, (void *)buf,
                                  sizeof(buf), 0, &from.sa, &fromlen);
        }

        if (count == -1 && try_again(SOCKERRNO))
          continue;
        else if (count <= 0)
          handle_error(channel, i, now);
#ifdef HAVE_RECVFROM
        else if (!same_address(&from.sa, &server->addr))
          /* The address the response comes from does not match the address we
           * sent the request to. Someone may be attempting to perform a cache
           * poisoning attack. */
          break;
#endif
        else
          process_answer(channel, buf, (int)count, i, 0, now);
       } while (count > 0);
    }
}