/*
 * Recv should not be called from an interrupt context, so the only time interrupts
 * must be disabled is when freeing a pbuf
 */
socket_error_t lwipv4_socket_recv_from(struct socket *socket, void * buf, size_t *len, struct socket_addr *addr, uint16_t *port)
{
    socket_error_t err = recv_validate(socket, buf, len);
    struct pbuf *p;
    if (err != SOCKET_ERROR_NONE) {
        return err;
    }
    if(addr == NULL || port == NULL) {
        return SOCKET_ERROR_NULL_PTR;
    }
    socket_addr_set_any(addr);
    p = (struct pbuf *)socket->rxBufChain;

    if (lwipv4_socket_is_connected(socket)) {
        if (socket->family == SOCKET_DGRAM) {
            struct udp_pcb * upcb = (struct udp_pcb *) socket->impl;
            socket_addr_set_ipv4_addr(addr, upcb->remote_ip.ip4.addr);
            *port = upcb->remote_port;
        } else if (socket->family == SOCKET_STREAM) {
            struct tcp_pcb * tpcb = (struct tcp_pcb *) socket->impl;
            socket_addr_set_ipv4_addr(addr, tpcb->remote_ip.ip4.addr);
            *port = tpcb->remote_port;
        }
    } else if (socket->family == SOCKET_DGRAM) {
        struct udp_hdr * udphdr;
        struct ip_hdr * iphdr;
        struct ip_addr srcip;
        /* roll back the pbuf by udp_hdr to find the source port. */
        pbuf_header(p, UDP_HLEN);
        udphdr = p->payload;
        /* roll back the pbuf by ip_hdr to find the source IP */
        pbuf_header(p, IP_HLEN);
        iphdr = p->payload;
        /* put the pbuf back where it was */
        pbuf_header(p, -UDP_HLEN - IP_HLEN);

        ip_addr_copy(srcip, iphdr->src);
        socket_addr_set_ipv4_addr(addr, srcip.addr);
        *port = ntohs(udphdr->src);
    }
    err = recv_copy_free(socket, buf, len);
    return err;
}
socket_error_t lwipv4_get_remote_addr(const struct socket *socket, struct socket_addr *addr)
{
    if (socket == NULL || socket->impl == NULL || addr == NULL)
    {
        return SOCKET_ERROR_NULL_PTR;
    }
    if (!lwipv4_socket_is_connected(socket)) {
        return SOCKET_ERROR_NO_CONNECTION;
    }
    struct ip_pcb *pcb = socket->impl;
    socket_addr_set_ipv4_addr(addr, pcb->remote_ip.ip4.addr);
    return SOCKET_ERROR_NONE;
}
socket_error_t lwipv4_get_local_addr(const struct socket *socket, struct socket_addr *addr)
{
    if (socket == NULL || socket->impl == NULL || addr == NULL)
    {
        return SOCKET_ERROR_NULL_PTR;
    }
    if (!lwipv4_socket_is_bound(socket)) {
        return SOCKET_ERROR_NOT_BOUND;
    }
    struct ip_pcb *pcb = socket->impl;
    socket_addr_set_ipv4_addr(addr, pcb->local_ip.ip4.addr);
    return SOCKET_ERROR_NONE;
}
static void dnscb(const char *name, struct ip_addr *addr, void *arg) {
  struct socket *sock = (struct socket *)arg;
  socket_api_handler_t handler = (socket_api_handler_t) sock->handler;
  socket_event_t e;
  if (addr == NULL) {
      e.event = SOCKET_EVENT_ERROR;
      e.i.e = SOCKET_ERROR_DNS_FAILED;
  } else {
      e.event = SOCKET_EVENT_DNS;
      // Install IPv4 prefix
      socket_addr_set_ipv4_addr(&e.i.d.addr, addr->addr);
      e.i.d.domain = name;
  }
  sock->event = &e;
  handler();
  sock->event = NULL;
}
static socket_error_t str2addr(const struct socket *sock, struct socket_addr *address, const char *addr)
{
    socket_error_t err = SOCKET_ERROR_NONE;
    switch(sock->stack)  {
    case SOCKET_STACK_LWIP_IPV4: {
        ip_addr_t a;
        if (ipaddr_aton(addr, &a) == -1) {
            err = SOCKET_ERROR_BAD_ADDRESS;
        } else {
            socket_addr_set_ipv4_addr(address, (uint32_t) a.addr);
        }
        break;
    }
    default:
        break;
    }
    return err;
}
示例#6
0
int
inet_aton(const char *cp, struct socket_addr *addr)
{
	u_long parts[4];
	in_addr_t val;
	const char *c;
	char *endptr;
	int gotend, n;

	c = (const char *)cp;
	n = 0;

	/*
	 * Run through the string, grabbing numbers until
	 * the end of the string, or some error
	 */
	gotend = 0;
	while (!gotend) {
		unsigned long l;

		l = strtoul(c, &endptr, 0);

		if (l == ULONG_MAX || (l == 0 && endptr == c))
			return (0);

		val = (in_addr_t)l;

		/*
		 * If the whole string is invalid, endptr will equal
		 * c.. this way we can make sure someone hasn't
		 * gone '.12' or something which would get past
		 * the next check.
		 */
		if (endptr == c)
			return (0);
		parts[n] = val;
		c = endptr;

		/* Check the next character past the previous number's end */
		switch (*c) {
		case '.' :

			/* Make sure we only do 3 dots .. */
			if (n == 3)	/* Whoops. Quit. */
				return (0);
			n++;
			c++;
			break;

		case '\0':
			gotend = 1;
			break;

		default:
			if (isspace((unsigned char)*c)) {
				gotend = 1;
				break;
			} else {

				/* Invalid character, then fail. */
				return (0);
			}
		}

	}

	/* Concoct the address according to the number of parts specified. */
	switch (n) {
	case 0:				/* a -- 32 bits */

		/*
		 * Nothing is necessary here.  Overflow checking was
		 * already done in strtoul().
		 */
		break;
	case 1:				/* a.b -- 8.24 bits */
		if (val > 0xffffff || parts[0] > 0xff)
			return (0);
		val |= parts[0] << 24;
		break;

	case 2:				/* a.b.c -- 8.8.16 bits */
		if (val > 0xffff || parts[0] > 0xff || parts[1] > 0xff)
			return (0);
		val |= (parts[0] << 24) | (parts[1] << 16);
		break;

	case 3:				/* a.b.c.d -- 8.8.8.8 bits */
		if (val > 0xff || parts[0] > 0xff || parts[1] > 0xff ||
		    parts[2] > 0xff)
			return (0);
		val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
		break;
	}

	if (addr != NULL)
		socket_addr_set_ipv4_addr(addr,val);
	return (1);
}