Esempio n. 1
0
static bool net_pkt_is_compact(struct net_pkt *pkt)
{
	struct net_buf *frag, *last;
	size_t total = 0, calc;
	int count = 0;

	last = NULL;
	frag = pkt->frags;

	while (frag) {
		total += frag->len;
		count++;

		last = frag;
		frag = frag->frags;
	}

	NET_ASSERT(last);

	if (!last) {
		return false;
	}

	calc = count * (last->size) - net_buf_tailroom(last) -
		count * (net_buf_headroom(last));

	if (total == calc) {
		return true;
	}

	NET_DBG("Not compacted total %zu real %zu", total, calc);

	return false;
}
Esempio n. 2
0
static inline struct net_nbr *get_nbr(struct net_nbr *start, int idx)
{
	NET_ASSERT(idx < CONFIG_NET_IPV6_MAX_NEIGHBORS);

	return (struct net_nbr *)((void *)start +
			((sizeof(struct net_nbr) + start->size) * idx));
}
Esempio n. 3
0
/* Called by driver when an IP packet has been received */
int net_recv_data(struct net_if *iface, struct net_pkt *pkt)
{
	NET_ASSERT(pkt && pkt->frags);
	NET_ASSERT(iface);

	if (!pkt->frags) {
		return -ENODATA;
	}

	if (!atomic_test_bit(iface->flags, NET_IF_UP)) {
		return -ENETDOWN;
	}

	NET_DBG("fifo %p iface %p pkt %p len %zu", &rx_queue, iface, pkt,
		net_pkt_get_len(pkt));

	net_pkt_set_iface(pkt, iface);

	k_fifo_put(&rx_queue, pkt);

	return 0;
}
Esempio n. 4
0
int net_nbr_unlink(struct net_nbr *nbr, struct net_linkaddr *lladdr)
{
	ARG_UNUSED(lladdr);

	if (nbr->idx == NET_NBR_LLADDR_UNKNOWN) {
		return -EALREADY;
	}

	NET_ASSERT(nbr->idx < CONFIG_NET_IPV6_MAX_NEIGHBORS);
	NET_ASSERT(net_neighbor_lladdr[nbr->idx].ref > 0);

	net_neighbor_lladdr[nbr->idx].ref--;

	if (!net_neighbor_lladdr[nbr->idx].ref) {
		memset(net_neighbor_lladdr[nbr->idx].lladdr.addr, 0,
		       sizeof(net_neighbor_lladdr[nbr->idx].lladdr.storage));
	}

	nbr->idx = NET_NBR_LLADDR_UNKNOWN;
	nbr->iface = NULL;

	return 0;
}
Esempio n. 5
0
struct net_pkt *net_ipv4_create(struct net_context *context,
				struct net_pkt *pkt,
				const struct in_addr *src,
				const struct in_addr *dst)
{
	NET_ASSERT(((struct sockaddr_in_ptr *)&context->local)->sin_addr);

	if (!src) {
		src = ((struct sockaddr_in_ptr *)&context->local)->sin_addr;
	}

	if (net_is_ipv4_addr_unspecified(src)
	    || net_is_ipv4_addr_mcast(src)) {
		src = &net_pkt_iface(pkt)->ipv4.unicast[0].address.in_addr;
	}

	return net_ipv4_create_raw(pkt,
				   src,
				   dst,
				   net_context_get_iface(context),
				   net_context_get_ip_proto(context));
}
Esempio n. 6
0
bool WriteTGA( const char filename[], int width, int height, uint8_t * ptr )
{
    FILE * file = fopen( filename, "wb" );
    if ( !file )
        return false;

    putc( 0, file );
    putc( 0, file );
    putc( 10, file );                        /* compressed RGB */
    putc( 0, file ); putc( 0, file );
    putc( 0, file ); putc( 0, file );
    putc( 0, file );
    putc( 0, file ); putc( 0, file );           /* X origin */
    putc( 0, file ); putc( 0, file );           /* y origin */
    putc( ( width & 0x00FF ),file );
    putc( ( width & 0xFF00 ) >> 8,file );
    putc( ( height & 0x00FF ), file );
    putc( ( height & 0xFF00 ) >> 8, file );
    putc( 24, file );                         /* 24 bit bitmap */
    putc( 0, file );

    for ( int y = 0; y < height; ++y )
    {
        uint8_t * line = ptr + width * 3 * y;
        uint8_t * end_of_line = line + width * 3;
        uint8_t * pixel = line;
        while ( true )
        {
            if ( pixel >= end_of_line )
                break;

            uint8_t * start = pixel;
            uint8_t * finish = pixel + 128 * 3;
            if ( finish > end_of_line )
                finish = end_of_line;
            uint32_t previous = ( pixel[0] << 16 ) | ( pixel[1] << 8 ) | pixel[2];
            pixel += 3;
            int counter = 1;

            // RLE packet
            while ( pixel < finish )
            {
                NET_ASSERT( pixel < end_of_line );
                uint32_t current = ( pixel[0] << 16 ) | ( pixel[1] << 8 ) | pixel[2];
                if ( current != previous )
                    break;
                previous = current;
                pixel += 3;
                counter++;
            }
            if ( counter > 1 )
            {
                NET_ASSERT( counter <= 128 );
                putc( uint8_t( counter - 1 ) | 128, file );
                putc( start[0], file );
                putc( start[1], file );
                putc( start[2], file );
                continue;
            }

            // RAW packet
            while ( pixel < finish )
            {
                NET_ASSERT( pixel < end_of_line );
                uint32_t current = ( pixel[0] << 16 ) | ( pixel[1] << 8 ) | pixel[2];
                if ( current == previous )
                    break;
                previous = current;
                pixel += 3;
                counter++;
            }
            NET_ASSERT( counter >= 1 );
            NET_ASSERT( counter <= 128 );
            putc( uint8_t( counter - 1 ), file );
            fwrite( start, counter * 3, 1, file );
        }
    }

    fclose( file );

    return true;
}
Esempio n. 7
0
static void https_handler(struct http_client_ctx *ctx,
			  struct k_sem *startup_sync)
{
	struct tx_fifo_block *tx_data;
	struct http_client_request req;
	size_t len;
	int ret;

	/* First mbedtls specific initialization */
	ret = https_init(ctx);

	k_sem_give(startup_sync);

	if (ret < 0) {
		return;
	}

reset:
	http_parser_init(&ctx->parser, HTTP_RESPONSE);
	ctx->rsp.data_len = 0;

	/* Wait that the sender sends the data, and the peer to respond to.
	 */
	tx_data = k_fifo_get(&ctx->https.mbedtls.ssl_ctx.tx_fifo, K_FOREVER);
	if (tx_data) {
		/* Because the req pointer might disappear as it is controlled
		 * by application, copy the data here.
		 */
		memcpy(&req, tx_data->req, sizeof(req));
	} else {
		NET_ASSERT(tx_data);
		goto reset;
	}

	print_info(ctx, ctx->req.method);

	/* If the connection is not active, then re-connect */
	ret = tcp_connect(ctx);
	if (ret < 0 && ret != -EALREADY) {
		k_sem_give(&ctx->req.wait);
		goto reset;
	}

	mbedtls_ssl_session_reset(&ctx->https.mbedtls.ssl);
	mbedtls_ssl_set_bio(&ctx->https.mbedtls.ssl, ctx, ssl_tx,
			    ssl_rx, NULL);

	/* SSL handshake. The ssl_rx() function will be called next by
	 * mbedtls library. The ssl_rx() will block and wait that data is
	 * received by ssl_received() and passed to it via fifo. After
	 * receiving the data, this function will then proceed with secure
	 * connection establishment.
	 */
	/* Waiting SSL handshake */
	do {
		ret = mbedtls_ssl_handshake(&ctx->https.mbedtls.ssl);
		if (ret != MBEDTLS_ERR_SSL_WANT_READ &&
		    ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
			if (ret == MBEDTLS_ERR_SSL_CONN_EOF) {
				goto close;
			}

			if (ret < 0) {
				print_error("mbedtls_ssl_handshake returned "
					    "-0x%x", ret);
				goto close;
			}
		}
	} while (ret != 0);

	ret = http_request(ctx, &req, BUF_ALLOC_TIMEOUT);

	k_mem_pool_free(&tx_data->block);

	if (ret < 0) {
		NET_DBG("Send error (%d)", ret);
		goto close;
	}

	NET_DBG("Read HTTPS response");

	do {
		len = ctx->rsp.response_buf_len - 1;
		memset(ctx->rsp.response_buf, 0, ctx->rsp.response_buf_len);

		ret = mbedtls_ssl_read(&ctx->https.mbedtls.ssl,
				       ctx->rsp.response_buf, len);
		if (ret == 0) {
			goto close;
		}

		if (ret == MBEDTLS_ERR_SSL_WANT_READ ||
		    ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
			continue;
		}

		if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
			NET_DBG("Connection was closed gracefully");
			goto close;
		}

		if (ret == MBEDTLS_ERR_NET_CONN_RESET) {
			NET_DBG("Connection was reset by peer");
			goto close;
		}

		if (ret == -EIO) {
			NET_DBG("Response received, waiting another ctx %p",
				ctx);
			goto next;
		}

		if (ret < 0) {
			print_error("mbedtls_ssl_read returned -0x%x", ret);
			goto close;
		}

		/* The data_len will count how many bytes we have read,
		 * this value is passed to user supplied response callback
		 * by on_body() and on_message_complete() functions.
		 */
		ctx->rsp.data_len += ret;

		ret = http_parser_execute(&ctx->parser,
					  &ctx->settings,
					  ctx->rsp.response_buf,
					  ret);
		if (!ret) {
			goto close;
		}

		ctx->rsp.data_len = 0;

		if (ret > 0) {
			/* Get more data */
			ret = MBEDTLS_ERR_SSL_WANT_READ;
		}
	} while (ret < 0);

close:
	/* If there is any pending data that have not been processed yet,
	 * we need to free it here.
	 */
	if (ctx->https.mbedtls.ssl_ctx.rx_pkt) {
		net_pkt_unref(ctx->https.mbedtls.ssl_ctx.rx_pkt);
		ctx->https.mbedtls.ssl_ctx.rx_pkt = NULL;
		ctx->https.mbedtls.ssl_ctx.frag = NULL;
	}

	NET_DBG("Resetting HTTPS connection %p", ctx);

	tcp_disconnect(ctx);

next:
	mbedtls_ssl_close_notify(&ctx->https.mbedtls.ssl);

	goto reset;
}
Esempio n. 8
0
static struct net_pkt *build_reply_pkt(const char *name,
				       struct net_context *context,
				       struct net_pkt *pkt)
{
	struct net_pkt *reply_pkt;
	struct net_buf *frag, *tmp;
	int header_len, recv_len, reply_len;

	NET_INFO("%s received %d bytes", name,
		 net_pkt_appdatalen(pkt));

	if (net_pkt_appdatalen(pkt) == 0) {
		return NULL;
	}

	reply_pkt = net_pkt_get_tx(context, K_FOREVER);

	NET_ASSERT(reply_pkt);

	recv_len = net_pkt_get_len(pkt);

	tmp = pkt->frags;

	/* First fragment will contain IP header so move the data
	 * down in order to get rid of it.
	 */
	header_len = net_pkt_appdata(pkt) - tmp->data;

	NET_ASSERT(header_len < CONFIG_NET_BUF_DATA_SIZE);

	/* After this pull, the tmp->data points directly to application
	 * data.
	 */
	net_buf_pull(tmp, header_len);

	while (tmp) {
		frag = net_pkt_get_data(context, K_FOREVER);

		if (!net_buf_headroom(tmp)) {
			/* If there is no link layer headers in the
			 * received fragment, then get rid of that also
			 * in the sending fragment. We end up here
			 * if MTU is larger than fragment size, this
			 * is typical for ethernet.
			 */
			net_buf_push(frag, net_buf_headroom(frag));

			frag->len = 0; /* to make fragment empty */

			/* Make sure to set the reserve so that
			 * in sending side we add the link layer
			 * header if needed.
			 */
			net_pkt_set_ll_reserve(reply_pkt, 0);
		}

		NET_ASSERT(net_buf_tailroom(frag) >= tmp->len);

		memcpy(net_buf_add(frag, tmp->len), tmp->data, tmp->len);

		net_pkt_frag_add(reply_pkt, frag);

		tmp = net_pkt_frag_del(pkt, NULL, tmp);
	}

	reply_len = net_pkt_get_len(reply_pkt);

	NET_ASSERT_INFO((recv_len - header_len) == reply_len,
			"Received %d bytes, sending %d bytes",
			recv_len - header_len, reply_len);

	return reply_pkt;
}