static void dns_cb(enum dns_resolve_status status, struct dns_addrinfo *info, void *user_data) { struct waiter *waiter = user_data; struct http_client_ctx *ctx = waiter->ctx; if (!(status == DNS_EAI_INPROGRESS && info)) { return; } if (info->ai_family == AF_INET) { #if defined(CONFIG_NET_IPV4) net_ipaddr_copy(&net_sin(&ctx->tcp.remote)->sin_addr, &net_sin(&info->ai_addr)->sin_addr); #else goto out; #endif } else if (info->ai_family == AF_INET6) { #if defined(CONFIG_NET_IPV6) net_ipaddr_copy(&net_sin6(&ctx->tcp.remote)->sin6_addr, &net_sin6(&info->ai_addr)->sin6_addr); #else goto out; #endif } else { goto out; } ctx->tcp.remote.family = info->ai_family; out: k_sem_give(&waiter->wait); }
static void set_ep_ports(int index) { #if defined(CONFIG_NET_IPV6) if (clients[index].bs_server.family == AF_INET6) { net_sin6(&clients[index].bs_server)->sin6_port = htons(LWM2M_BOOTSTRAP_PORT); } if (clients[index].reg_server.family == AF_INET6) { net_sin6(&clients[index].reg_server)->sin6_port = htons(LWM2M_PEER_PORT); } #endif #if defined(CONFIG_NET_IPV4) if (clients[index].bs_server.family == AF_INET) { net_sin(&clients[index].bs_server)->sin_port = htons(LWM2M_BOOTSTRAP_PORT); } if (clients[index].reg_server.family == AF_INET) { net_sin(&clients[index].reg_server)->sin_port = htons(LWM2M_PEER_PORT); } #endif }
static int get_local_addr(struct http_client_ctx *ctx) { if (ctx->tcp.local.family == AF_INET6) { #if defined(CONFIG_NET_IPV6) struct in6_addr *dst = &net_sin6(&ctx->tcp.remote)->sin6_addr; net_ipaddr_copy(&net_sin6(&ctx->tcp.local)->sin6_addr, net_if_ipv6_select_src_addr(NULL, dst)); #else return -EPFNOSUPPORT; #endif } else if (ctx->tcp.local.family == AF_INET) { #if defined(CONFIG_NET_IPV4) struct net_if *iface = net_if_get_default(); /* For IPv4 we take the first address in the interface */ net_ipaddr_copy(&net_sin(&ctx->tcp.local)->sin_addr, &iface->ipv4.unicast[0].address.in_addr); #else return -EPFNOSUPPORT; #endif } return 0; }
static bool peer_addr_exist(struct sockaddr *peer_addr) { bool ret = false; int i; /* look for duplicate peer_addr */ for (i = 0; i < client_count; i++) { #if defined(CONFIG_NET_IPV6) if (peer_addr->family == AF_INET6 && net_ipv6_addr_cmp( &net_sin6(&clients[i].bs_server)->sin6_addr, &net_sin6(peer_addr)->sin6_addr)) { ret = true; break; } if (peer_addr->family == AF_INET6 && net_ipv6_addr_cmp( &net_sin6(&clients[i].reg_server)->sin6_addr, &net_sin6(peer_addr)->sin6_addr)) { ret = true; break; } #endif #if defined(CONFIG_NET_IPV4) if (peer_addr->family == AF_INET && net_ipv4_addr_cmp( &net_sin(&clients[i].bs_server)->sin_addr, &net_sin(peer_addr)->sin_addr)) { ret = true; break; } if (peer_addr->family == AF_INET && net_ipv4_addr_cmp( &net_sin(&clients[i].reg_server)->sin_addr, &net_sin(peer_addr)->sin_addr)) { ret = true; break; } #endif } return ret; }
static void sprint_addr(char *buf, int len, sa_family_t family, struct sockaddr *addr) { if (family == AF_INET6) { net_addr_ntop(AF_INET6, &net_sin6(addr)->sin6_addr, buf, len); } else if (family == AF_INET) { net_addr_ntop(AF_INET, &net_sin(addr)->sin_addr, buf, len); } else { NET_DBG("Invalid protocol family"); } }
static inline void set_dst_addr(sa_family_t family, struct net_pkt *pkt, struct sockaddr *dst_addr) { #if defined(CONFIG_NET_IPV6) if (family == AF_INET6) { net_ipaddr_copy(&net_sin6(dst_addr)->sin6_addr, &NET_IPV6_HDR(pkt)->src); net_sin6(dst_addr)->sin6_family = AF_INET6; net_sin6(dst_addr)->sin6_port = NET_UDP_HDR(pkt)->src_port; } #endif /* CONFIG_NET_IPV6) */ #if defined(CONFIG_NET_IPV4) if (family == AF_INET) { net_ipaddr_copy(&net_sin(dst_addr)->sin_addr, &NET_IPV4_HDR(pkt)->src); net_sin(dst_addr)->sin_family = AF_INET; net_sin(dst_addr)->sin_port = NET_UDP_HDR(pkt)->src_port; } #endif /* CONFIG_NET_IPV6) */ }
static inline void print_info(struct http_client_ctx *ctx, enum http_method method) { #if defined(CONFIG_NET_DEBUG_HTTP) char local[NET_IPV6_ADDR_LEN]; char remote[NET_IPV6_ADDR_LEN]; sprint_addr(local, NET_IPV6_ADDR_LEN, ctx->tcp.local.family, &ctx->tcp.local); sprint_addr(remote, NET_IPV6_ADDR_LEN, ctx->tcp.remote.family, &ctx->tcp.remote); NET_DBG("HTTP %s (%s) %s -> %s port %d", http_method_str(method), ctx->req.host, local, remote, ntohs(net_sin(&ctx->tcp.remote)->sin_port)); #endif }
static int tcp_connect(struct http_client_ctx *ctx) { socklen_t addrlen = sizeof(struct sockaddr_in); int ret; if (ctx->tcp.ctx && net_context_is_used(ctx->tcp.ctx) && net_context_get_state(ctx->tcp.ctx) == NET_CONTEXT_CONNECTED) { /* If we are already connected, then just return */ return -EALREADY; } if (ctx->tcp.remote.family == AF_INET6) { addrlen = sizeof(struct sockaddr_in6); /* If we are reconnecting, then make sure the source port * is re-calculated so that the peer will not get confused * which connection the connection is related to. * This was seen in Linux which dropped packets when the same * source port was for a new connection after the old connection * was terminated. */ net_sin6(&ctx->tcp.local)->sin6_port = 0; } else { net_sin(&ctx->tcp.local)->sin_port = 0; } ret = get_local_addr(ctx); if (ret < 0) { NET_DBG("Cannot get local address (%d)", ret); return ret; } ret = net_context_get(ctx->tcp.remote.family, SOCK_STREAM, IPPROTO_TCP, &ctx->tcp.ctx); if (ret) { NET_DBG("Get context error (%d)", ret); return ret; } net_context_setup_pools(ctx->tcp.ctx, ctx->tx_slab, ctx->data_pool); ret = net_context_bind(ctx->tcp.ctx, &ctx->tcp.local, addrlen); if (ret) { NET_DBG("Bind error (%d)", ret); goto out; } ret = net_context_connect(ctx->tcp.ctx, &ctx->tcp.remote, addrlen, NULL, ctx->tcp.timeout, NULL); if (ret) { NET_DBG("Connect error (%d)", ret); goto out; } return net_context_recv(ctx->tcp.ctx, ctx->tcp.recv_cb, K_NO_WAIT, ctx); out: net_context_put(ctx->tcp.ctx); ctx->tcp.ctx = NULL; return ret; }
static inline int set_remote_addr(struct http_client_ctx *ctx, const char *server, u16_t server_port) { int ret; #if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4) ret = net_addr_pton(AF_INET6, server, &net_sin6(&ctx->tcp.remote)->sin6_addr); if (ret < 0) { /* Could be hostname, try DNS if configured. */ #if !defined(CONFIG_DNS_RESOLVER) NET_ERR("Invalid IPv6 address %s", server); return -EINVAL; #else ret = resolve_name(ctx, server, DNS_QUERY_TYPE_AAAA); if (ret < 0) { NET_ERR("Cannot resolve %s (%d)", server, ret); return ret; } #endif } net_sin6(&ctx->tcp.remote)->sin6_port = htons(server_port); net_sin6(&ctx->tcp.remote)->sin6_family = AF_INET6; #endif /* IPV6 && !IPV4 */ #if defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6) ret = net_addr_pton(AF_INET, server, &net_sin(&ctx->tcp.remote)->sin_addr); if (ret < 0) { /* Could be hostname, try DNS if configured. */ #if !defined(CONFIG_DNS_RESOLVER) NET_ERR("Invalid IPv4 address %s", server); return -EINVAL; #else ret = resolve_name(ctx, server, DNS_QUERY_TYPE_A); if (ret < 0) { NET_ERR("Cannot resolve %s (%d)", server, ret); return ret; } #endif } net_sin(&ctx->tcp.remote)->sin_port = htons(server_port); net_sin(&ctx->tcp.remote)->sin_family = AF_INET; #endif /* IPV6 && !IPV4 */ #if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_IPV6) ret = net_addr_pton(AF_INET, server, &net_sin(&ctx->tcp.remote)->sin_addr); if (ret < 0) { ret = net_addr_pton(AF_INET6, server, &net_sin6(&ctx->tcp.remote)->sin6_addr); if (ret < 0) { /* Could be hostname, try DNS if configured. */ #if !defined(CONFIG_DNS_RESOLVER) NET_ERR("Invalid IPv4 or IPv6 address %s", server); return -EINVAL; #else ret = resolve_name(ctx, server, DNS_QUERY_TYPE_A); if (ret < 0) { ret = resolve_name(ctx, server, DNS_QUERY_TYPE_AAAA); if (ret < 0) { NET_ERR("Cannot resolve %s (%d)", server, ret); return ret; } goto ipv6; } goto ipv4; #endif /* !CONFIG_DNS_RESOLVER */ } else { #if defined(CONFIG_DNS_RESOLVER) ipv6: #endif net_sin6(&ctx->tcp.remote)->sin6_port = htons(server_port); net_sin6(&ctx->tcp.remote)->sin6_family = AF_INET6; } } else { #if defined(CONFIG_DNS_RESOLVER) ipv4: #endif net_sin(&ctx->tcp.remote)->sin_port = htons(server_port); net_sin(&ctx->tcp.remote)->sin_family = AF_INET; } #endif /* IPV4 && IPV6 */ /* If we have not yet figured out what is the protocol family, * then we cannot continue. */ if (ctx->tcp.remote.family == AF_UNSPEC) { NET_ERR("Unknown protocol family."); return -EPFNOSUPPORT; } return 0; }