/* * 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; }
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); }