/* ** 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; }
/*-------------------------------------------------------------------------*\ * 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; }
/* ** 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; }
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); } }
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; }
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; }
/* * 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); }
/*-------------------------------------------------------------------------*\ * 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; } }
nsapi_size_or_error_t NanostackInterface::socket_recv(void *handle, void *data, nsapi_size_t size) { return socket_recvfrom(handle, NULL, data, size); }
/* 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); }
/** 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; }
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; }
/* * 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 */ }
/* 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); }
/* 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); } }