static void setup_ipv4_udp(struct net_pkt *pkt, struct in_addr *remote_addr, struct in_addr *local_addr, u16_t remote_port, u16_t local_port) { NET_IPV4_HDR(pkt)->vhl = 0x45; NET_IPV4_HDR(pkt)->tos = 0; NET_IPV4_HDR(pkt)->len[0] = 0; NET_IPV4_HDR(pkt)->len[1] = NET_UDPH_LEN + sizeof(struct net_ipv4_hdr) + strlen(payload); NET_IPV4_HDR(pkt)->proto = IPPROTO_UDP; net_ipaddr_copy(&NET_IPV4_HDR(pkt)->src, remote_addr); net_ipaddr_copy(&NET_IPV4_HDR(pkt)->dst, local_addr); net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv4_hdr)); net_pkt_set_ipv6_ext_len(pkt, 0); net_buf_add(pkt->frags, net_pkt_ip_hdr_len(pkt) + sizeof(struct net_udp_hdr)); NET_UDP_HDR(pkt)->src_port = htons(remote_port); NET_UDP_HDR(pkt)->dst_port = htons(local_port); net_buf_add_mem(pkt->frags, payload, strlen(payload)); }
static void setup_ipv6_udp(struct net_pkt *pkt, struct in6_addr *remote_addr, struct in6_addr *local_addr, u16_t remote_port, u16_t local_port) { NET_IPV6_HDR(pkt)->vtc = 0x60; NET_IPV6_HDR(pkt)->tcflow = 0; NET_IPV6_HDR(pkt)->flow = 0; NET_IPV6_HDR(pkt)->len[0] = 0; NET_IPV6_HDR(pkt)->len[1] = NET_UDPH_LEN + strlen(payload); NET_IPV6_HDR(pkt)->nexthdr = IPPROTO_UDP; NET_IPV6_HDR(pkt)->hop_limit = 255; net_ipaddr_copy(&NET_IPV6_HDR(pkt)->src, remote_addr); net_ipaddr_copy(&NET_IPV6_HDR(pkt)->dst, local_addr); net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv6_hdr)); net_pkt_set_ipv6_ext_len(pkt, 0); net_buf_add(pkt->frags, net_pkt_ip_hdr_len(pkt) + sizeof(struct net_udp_hdr)); NET_UDP_HDR(pkt)->src_port = htons(remote_port); NET_UDP_HDR(pkt)->dst_port = htons(local_port); net_buf_add_mem(pkt->frags, payload, strlen(payload)); }
u16_t net_calc_chksum(struct net_pkt *pkt, u8_t proto) { u16_t upper_layer_len; u16_t sum; switch (net_pkt_family(pkt)) { #if defined(CONFIG_NET_IPV4) case AF_INET: upper_layer_len = (NET_IPV4_HDR(pkt)->len[0] << 8) + NET_IPV4_HDR(pkt)->len[1] - net_pkt_ipv6_ext_len(pkt) - net_pkt_ip_hdr_len(pkt); if (proto == IPPROTO_ICMP) { return htons(calc_chksum(0, net_pkt_ip_data(pkt) + net_pkt_ip_hdr_len(pkt), upper_layer_len)); } else { sum = calc_chksum(upper_layer_len + proto, (u8_t *)&NET_IPV4_HDR(pkt)->src, 2 * sizeof(struct in_addr)); } break; #endif #if defined(CONFIG_NET_IPV6) case AF_INET6: upper_layer_len = (NET_IPV6_HDR(pkt)->len[0] << 8) + NET_IPV6_HDR(pkt)->len[1] - net_pkt_ipv6_ext_len(pkt); sum = calc_chksum(upper_layer_len + proto, (u8_t *)&NET_IPV6_HDR(pkt)->src, 2 * sizeof(struct in6_addr)); break; #endif default: NET_DBG("Unknown protocol family %d", net_pkt_family(pkt)); return 0; } sum = calc_chksum_pkt(sum, pkt, upper_layer_len); sum = (sum == 0) ? 0xffff : htons(sum); return sum; }
static inline u16_t calc_chksum_pkt(u16_t sum, struct net_pkt *pkt, u16_t upper_layer_len) { struct net_buf *frag = pkt->frags; u16_t proto_len = net_pkt_ip_hdr_len(pkt) + net_pkt_ipv6_ext_len(pkt); s16_t len = frag->len - proto_len; u8_t *ptr = frag->data + proto_len; ARG_UNUSED(upper_layer_len); if (len < 0) { NET_DBG("1st fragment len %u < IP header len %u", frag->len, proto_len); return 0; } while (frag) { sum = calc_chksum(sum, ptr, len); frag = frag->frags; if (!frag) { break; } ptr = frag->data; /* Do we need to take first byte from next fragment */ if (len % 2) { u16_t tmp = *ptr; sum += tmp; if (sum < tmp) { sum++; } len = frag->len - 1; ptr++; } else { len = frag->len; } } return sum; }
int http_request(struct http_client_ctx *ctx, struct http_client_request *req, s32_t timeout) { const char *method = http_method_str(req->method); struct net_pkt *pkt; int ret = -ENOMEM; pkt = net_pkt_get_tx(ctx->tcp.ctx, timeout); if (!pkt) { return -ENOMEM; } if (!net_pkt_append_all(pkt, strlen(method), (u8_t *)method, timeout)) { goto out; } /* Space after method string. */ if (!net_pkt_append_all(pkt, 1, (u8_t *)" ", timeout)) { goto out; } if (!net_pkt_append_all(pkt, strlen(req->url), (u8_t *)req->url, timeout)) { goto out; } if (!net_pkt_append_all(pkt, strlen(req->protocol), (u8_t *)req->protocol, timeout)) { goto out; } if (req->host) { if (!net_pkt_append_all(pkt, strlen(HTTP_HOST), (u8_t *)HTTP_HOST, timeout)) { goto out; } if (!net_pkt_append_all(pkt, strlen(req->host), (u8_t *)req->host, timeout)) { goto out; } if (!net_pkt_append_all(pkt, strlen(HTTP_CRLF), (u8_t *)HTTP_CRLF, timeout)) { goto out; } } if (req->header_fields) { if (!net_pkt_append_all(pkt, strlen(req->header_fields), (u8_t *)req->header_fields, timeout)) { goto out; } } if (req->content_type_value) { if (!net_pkt_append_all(pkt, strlen(HTTP_CONTENT_TYPE), (u8_t *)HTTP_CONTENT_TYPE, timeout)) { goto out; } if (!net_pkt_append_all(pkt, strlen(req->content_type_value), (u8_t *)req->content_type_value, timeout)) { goto out; } } if (req->payload && req->payload_size) { char content_len_str[HTTP_CONT_LEN_SIZE]; ret = snprintk(content_len_str, HTTP_CONT_LEN_SIZE, HTTP_CRLF "Content-Length: %u" HTTP_CRLF HTTP_CRLF, req->payload_size); if (ret <= 0 || ret >= HTTP_CONT_LEN_SIZE) { ret = -ENOMEM; goto out; } if (!net_pkt_append_all(pkt, ret, (u8_t *)content_len_str, timeout)) { ret = -ENOMEM; goto out; } if (!net_pkt_append_all(pkt, req->payload_size, (u8_t *)req->payload, timeout)) { ret = -ENOMEM; goto out; } } else { if (!net_pkt_append_all(pkt, strlen(HTTP_EOF), (u8_t *)HTTP_EOF, timeout)) { goto out; } } #if defined(CONFIG_NET_IPV6) if (net_pkt_family(pkt) == AF_INET6) { net_pkt_set_appdatalen(pkt, net_pkt_get_len(pkt) - net_pkt_ip_hdr_len(pkt) - net_pkt_ipv6_ext_opt_len(pkt)); } else #endif { net_pkt_set_appdatalen(pkt, net_pkt_get_len(pkt) - net_pkt_ip_hdr_len(pkt)); } ret = ctx->tcp.send_data(pkt, NULL, timeout, NULL, ctx); if (ret == 0) { return 0; } out: net_pkt_unref(pkt); return ret; }
/* This gets plain data and it sends encrypted one to peer */ static int https_send(struct net_pkt *pkt, net_context_send_cb_t cb, s32_t timeout, void *token, void *user_data) { struct http_client_ctx *ctx = user_data; int ret; u16_t len; if (!ctx->rsp.response_buf || ctx->rsp.response_buf_len == 0) { NET_DBG("Response buf not setup"); return -EINVAL; } len = net_pkt_appdatalen(pkt); if (len == 0) { NET_DBG("No application data to send"); return -EINVAL; } ret = net_frag_linearize(ctx->rsp.response_buf, ctx->rsp.response_buf_len, pkt, net_pkt_ip_hdr_len(pkt) + net_pkt_ipv6_ext_opt_len(pkt), len); if (ret < 0) { NET_DBG("Cannot linearize send data (%d)", ret); return ret; } if (ret != len) { NET_DBG("Linear copy error (%u vs %d)", len, ret); return -EINVAL; } do { ret = mbedtls_ssl_write(&ctx->https.mbedtls.ssl, ctx->rsp.response_buf, len); if (ret == MBEDTLS_ERR_NET_CONN_RESET) { NET_ERR("peer closed the connection -0x%x", ret); goto out; } if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { if (ret < 0) { print_error("mbedtls_ssl_write returned -0x%x", ret); goto out; } } } while (ret <= 0); out: if (cb) { cb(net_pkt_context(pkt), ret, token, user_data); } return ret; }