/** * Create (allocate) and initialize a new netbuf. * The netbuf doesn't yet contain a packet buffer! * * @return a pointer to a new netbuf * NULL on lack of memory */ struct netbuf *netbuf_new(void) { struct netbuf *buf; buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); if (buf != NULL) { buf->p = NULL; buf->ptr = NULL; ip_addr_set_any(&buf->addr); buf->port = 0; #if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY #if LWIP_CHECKSUM_ON_COPY buf->flags = 0; #endif /* LWIP_CHECKSUM_ON_COPY */ buf->toport_chksum = 0; #if LWIP_NETBUF_RECVINFO ip_addr_set_any(&buf->toaddr); #endif /* LWIP_NETBUF_RECVINFO */ #endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */ return buf; } else { return NULL; } }
static void close_handle(void) { tftp_state.port = 0; ip_addr_set_any(0, &tftp_state.addr); if(tftp_state.last_data != NULL) { pbuf_free(tftp_state.last_data); tftp_state.last_data = NULL; } sys_untimeout(tftp_tmr, NULL); if (tftp_state.handle) { tftp_state.ctx->close(tftp_state.handle); tftp_state.handle = NULL; LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: closing\n")); } }
/** * Inserts ipRouteTable indexes (.ipRouteDest) * into index tree. * * @param dflt non-zero for the default rte, zero for network rte * @param ni points to network interface for this rte * * @todo record sysuptime for _this_ route when it is installed * (needed for ipRouteAge) in the netif. */ void snmp_insert_iprteidx_tree(u8_t dflt, struct netif *ni) { u8_t insert = 0; ip_addr_t dst; if (dflt != 0) { /* the default route 0.0.0.0 */ ip_addr_set_any(&dst); insert = 1; } else { /* route to the network address */ ip_addr_get_network(&dst, &ni->ip_addr, &ni->netmask); /* exclude 0.0.0.0 network (reserved for default rte) */ if (!ip_addr_isany(&dst)) { insert = 1; } } if (insert) { struct mib_list_r
/** * Translates the name of a service location (for example, a host name) and/or * a service name and returns a set of socket addresses and associated * information to be used in creating a socket with which to address the * specified service. * Memory for the result is allocated internally and must be freed by calling * lwip_freeaddrinfo()! * * Due to a limitation in dns_gethostbyname, only the first address of a * host is returned. * Also, service names are not supported (only port numbers)! * * @param nodename descriptive name or address string of the host * (may be NULL -> local address) * @param servname port number as string of NULL * @param hints structure containing input values that set socktype and protocol * @param res pointer to a pointer where to store the result (set to NULL on failure) * @return 0 on success, non-zero on failure * * @todo: implement AI_V4MAPPED, AI_ADDRCONFIG */ int lwip_getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res) { err_t err; ip_addr_t addr; struct addrinfo *ai; struct sockaddr_storage *sa = NULL; int port_nr = 0; size_t total_size; size_t namelen = 0; int ai_family; if (res == NULL) { return EAI_FAIL; } *res = NULL; if ((nodename == NULL) && (servname == NULL)) { return EAI_NONAME; } if (hints != NULL) { ai_family = hints->ai_family; if ((ai_family != AF_UNSPEC) #if LWIP_IPV4 && (ai_family != AF_INET) #endif /* LWIP_IPV4 */ #if LWIP_IPV6 && (ai_family != AF_INET6) #endif /* LWIP_IPV6 */ ) { return EAI_FAMILY; } } else { ai_family = AF_UNSPEC; } if (servname != NULL) { /* service name specified: convert to port number * @todo?: currently, only ASCII integers (port numbers) are supported (AI_NUMERICSERV)! */ port_nr = atoi(servname); if ((port_nr <= 0) || (port_nr > 0xffff)) { return EAI_SERVICE; } } if (nodename != NULL) { /* service location specified, try to resolve */ if ((hints != NULL) && (hints->ai_flags & AI_NUMERICHOST)) { /* no DNS lookup, just parse for an address string */ if (!ipaddr_aton(nodename, &addr)) { return EAI_NONAME; } #if LWIP_IPV4 && LWIP_IPV6 if ((IP_IS_V6_VAL(addr) && ai_family == AF_INET) || (IP_IS_V4_VAL(addr) && ai_family == AF_INET6)) { return EAI_NONAME; } #endif /* LWIP_IPV4 && LWIP_IPV6 */ } else { #if LWIP_IPV4 && LWIP_IPV6 /* AF_UNSPEC: prefer IPv4 */ u8_t type = NETCONN_DNS_IPV4_IPV6; if (ai_family == AF_INET) { type = NETCONN_DNS_IPV4; } else if (ai_family == AF_INET6) { type = NETCONN_DNS_IPV6; } #endif /* LWIP_IPV4 && LWIP_IPV6 */ err = netconn_gethostbyname_addrtype(nodename, &addr, type); if (err != ERR_OK) { return EAI_FAIL; } } } else { /* service location specified, use loopback address */ if ((hints != NULL) && (hints->ai_flags & AI_PASSIVE)) { ip_addr_set_any(ai_family == AF_INET6, &addr); } else { ip_addr_set_loopback(ai_family == AF_INET6, &addr); } } total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_storage); if (nodename != NULL) { namelen = strlen(nodename); if (namelen > DNS_MAX_NAME_LENGTH) { /* invalid name length */ return EAI_FAIL; } LWIP_ASSERT("namelen is too long", total_size + namelen + 1 > total_size); total_size += namelen + 1; } /* If this fails, please report to lwip-devel! :-) */ LWIP_ASSERT("total_size <= NETDB_ELEM_SIZE: please report this!", total_size <= NETDB_ELEM_SIZE); ai = (struct addrinfo *)memp_malloc(MEMP_NETDB); if (ai == NULL) { return EAI_MEMORY; } memset(ai, 0, total_size); /* cast through void* to get rid of alignment warnings */ sa = (struct sockaddr_storage *)(void*)((u8_t*)ai + sizeof(struct addrinfo)); if (IP_IS_V6_VAL(addr)) { #if LWIP_IPV6 struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)sa; /* set up sockaddr */ inet6_addr_from_ip6addr(&sa6->sin6_addr, ip_2_ip6(&addr)); sa6->sin6_family = AF_INET6; sa6->sin6_len = sizeof(struct sockaddr_in6); sa6->sin6_port = lwip_htons((u16_t)port_nr); ai->ai_family = AF_INET6; #endif /* LWIP_IPV6 */ } else { #if LWIP_IPV4 struct sockaddr_in *sa4 = (struct sockaddr_in*)sa; /* set up sockaddr */ inet4_addr_from_ip4addr(&sa4->sin_addr, ip_2_ip4(&addr)); sa4->sin_family = AF_INET; sa4->sin_len = sizeof(struct sockaddr_in); sa4->sin_port = lwip_htons((u16_t)port_nr); ai->ai_family = AF_INET; #endif /* LWIP_IPV4 */ } /* set up addrinfo */ if (hints != NULL) { /* copy socktype & protocol from hints if specified */ ai->ai_socktype = hints->ai_socktype; ai->ai_protocol = hints->ai_protocol; } if (nodename != NULL) { /* copy nodename to canonname if specified */ ai->ai_canonname = ((char*)ai + sizeof(struct addrinfo) + sizeof(struct sockaddr_storage)); MEMCPY(ai->ai_canonname, nodename, namelen); ai->ai_canonname[namelen] = 0; } ai->ai_addrlen = sizeof(struct sockaddr_storage); ai->ai_addr = (struct sockaddr*)sa; *res = ai; return 0; }
static nsapi_error_t mbed_lwip_setsockopt(nsapi_stack_t *stack, nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen) { struct lwip_socket *s = (struct lwip_socket *)handle; switch (optname) { #if LWIP_TCP case NSAPI_KEEPALIVE: if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) { return NSAPI_ERROR_UNSUPPORTED; } s->conn->pcb.tcp->so_options |= SOF_KEEPALIVE; return 0; case NSAPI_KEEPIDLE: if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) { return NSAPI_ERROR_UNSUPPORTED; } s->conn->pcb.tcp->keep_idle = *(int*)optval; return 0; case NSAPI_KEEPINTVL: if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) { return NSAPI_ERROR_UNSUPPORTED; } s->conn->pcb.tcp->keep_intvl = *(int*)optval; return 0; #endif case NSAPI_REUSEADDR: if (optlen != sizeof(int)) { return NSAPI_ERROR_UNSUPPORTED; } if (*(int *)optval) { ip_set_option(s->conn->pcb.ip, SOF_REUSEADDR); } else { ip_reset_option(s->conn->pcb.ip, SOF_REUSEADDR); } return 0; case NSAPI_ADD_MEMBERSHIP: case NSAPI_DROP_MEMBERSHIP: { if (optlen != sizeof(nsapi_ip_mreq_t)) { return NSAPI_ERROR_PARAMETER; } err_t igmp_err; const nsapi_ip_mreq_t *imr = optval; /* Check interface address type matches group, or is unspecified */ if (imr->imr_interface.version != NSAPI_UNSPEC && imr->imr_interface.version != imr->imr_multiaddr.version) { return NSAPI_ERROR_PARAMETER; } ip_addr_t if_addr; ip_addr_t multi_addr; /* Convert the group address */ if (!convert_mbed_addr_to_lwip(&multi_addr, &imr->imr_multiaddr)) { return NSAPI_ERROR_PARAMETER; } /* Convert the interface address, or make sure it's the correct sort of "any" */ if (imr->imr_interface.version != NSAPI_UNSPEC) { if (!convert_mbed_addr_to_lwip(&if_addr, &imr->imr_interface)) { return NSAPI_ERROR_PARAMETER; } } else { ip_addr_set_any(IP_IS_V6(&if_addr), &if_addr); } igmp_err = ERR_USE; // Maps to NSAPI_ERROR_UNSUPPORTED int32_t member_pair_index = find_multicast_member(s, imr); if (optname == NSAPI_ADD_MEMBERSHIP) { if (!s->multicast_memberships) { // First multicast join on this socket, allocate space for membership tracking s->multicast_memberships = malloc(sizeof(nsapi_ip_mreq_t) * LWIP_SOCKET_MAX_MEMBERSHIPS); if (!s->multicast_memberships) { return NSAPI_ERROR_NO_MEMORY; } } else if(s->multicast_memberships_count == LWIP_SOCKET_MAX_MEMBERSHIPS) { return NSAPI_ERROR_NO_MEMORY; } if (member_pair_index != -1) { return NSAPI_ERROR_ADDRESS_IN_USE; } member_pair_index = next_free_multicast_member(s, 0); sys_prot_t prot = sys_arch_protect(); #if LWIP_IPV4 if (IP_IS_V4(&if_addr)) { igmp_err = igmp_joingroup(ip_2_ip4(&if_addr), ip_2_ip4(&multi_addr)); } #endif #if LWIP_IPV6 if (IP_IS_V6(&if_addr)) { igmp_err = mld6_joingroup(ip_2_ip6(&if_addr), ip_2_ip6(&multi_addr)); } #endif sys_arch_unprotect(prot); if (igmp_err == ERR_OK) { set_multicast_member_registry_bit(s, member_pair_index); s->multicast_memberships[member_pair_index] = *imr; s->multicast_memberships_count++; } } else { if (member_pair_index == -1) { return NSAPI_ERROR_NO_ADDRESS; } clear_multicast_member_registry_bit(s, member_pair_index); s->multicast_memberships_count--; sys_prot_t prot = sys_arch_protect(); #if LWIP_IPV4 if (IP_IS_V4(&if_addr)) { igmp_err = igmp_leavegroup(ip_2_ip4(&if_addr), ip_2_ip4(&multi_addr)); } #endif #if LWIP_IPV6 if (IP_IS_V6(&if_addr)) { igmp_err = mld6_leavegroup(ip_2_ip6(&if_addr), ip_2_ip6(&multi_addr)); } #endif sys_arch_unprotect(prot); } return mbed_lwip_err_remap(igmp_err); } default: return NSAPI_ERROR_UNSUPPORTED; } }