示例#1
0
void net_context_put(struct net_context *context)
{
	if (!context) {
		return;
	}

	nano_sem_take(&contexts_lock, TICKS_UNLIMITED);

	if (context->tuple.ip_proto == IPPROTO_UDP) {
		if (net_context_get_receiver_registered(context)) {
			struct simple_udp_connection *udp =
				net_context_get_udp_connection(context);
				simple_udp_unregister(udp);
		}
	}

#ifdef CONFIG_NETWORKING_WITH_TCP
	if (context->tcp_type == NET_TCP_TYPE_SERVER) {
		tcp_unlisten(UIP_HTONS(context->tuple.local_port),
			     &context->tcp);
	}
#endif

	memset(&context->tuple, 0, sizeof(context->tuple));
	memset(&context->udp, 0, sizeof(context->udp));
	context->receiver_registered = false;

	context_sem_give(&contexts_lock);
}
示例#2
0
/*---------------------------------------------------------------------------*/
static int prepare_and_send_buf(coap_context_t *ctx, session_t *session,
				uint8_t *data, size_t len)
{
  struct net_buf *buf;
  int max_data_len;

  /* This net_buf gets sent to network, so it is not released
   * by this function unless there was an error and buf was
   * not actually sent.
   */
  buf = ip_buf_get_tx(ctx->net_ctx);
  if (!buf) {
    len = -ENOBUFS;
    goto out;
  }

  max_data_len = IP_BUF_MAX_DATA - UIP_IPUDPH_LEN;

  PRINTF("%s: reply to peer data %p len %d\n", __FUNCTION__, data, len);

  if (len > max_data_len) {
    PRINTF("%s: too much (%d bytes) data to send (max %d bytes)\n",
	  __FUNCTION__, len, max_data_len);
    ip_buf_unref(buf);
    len = -EINVAL;
    goto out;
  }

  /* Note that we have reversed the addresses here
   * because net_reply() will reverse them again.
   */
#ifdef CONFIG_NETWORKING_WITH_IPV6
  uip_ip6addr_copy(&NET_BUF_IP(buf)->destipaddr, (uip_ip6addr_t *)&ctx->my_addr.in6_addr);
  uip_ip6addr_copy(&NET_BUF_IP(buf)->srcipaddr,
		   (uip_ip6addr_t *)&session->addr.ipaddr);
#else
  uip_ip4addr_copy(&NET_BUF_IP(buf)->destipaddr,
		   (uip_ip4addr_t *)&ctx->my_addr.in_addr);
  uip_ip4addr_copy(&NET_BUF_IP(buf)->srcipaddr,
		   (uip_ip4addr_t *)&session->addr.ipaddr);
#endif
  NET_BUF_UDP(buf)->destport = uip_ntohs(ctx->my_port);
  NET_BUF_UDP(buf)->srcport = session->addr.port;

  uip_set_udp_conn(buf) = net_context_get_udp_connection(ctx->net_ctx);

  memcpy(net_buf_add(buf, len), data, len);
  ip_buf_appdatalen(buf) = len;
  ip_buf_appdata(buf) = buf->data + ip_buf_reserve(buf);

  if (net_reply(ctx->net_ctx, buf)) {
    ip_buf_unref(buf);
  }
out:
  return len;
}
示例#3
0
/* Internal function to send network data to uIP stack */
static int check_and_send_packet(struct net_buf *buf)
{
	struct net_tuple *tuple;
	struct simple_udp_connection *udp;
	int ret = 0;

	if (!netdev.drv) {
		return -EINVAL;
	}

	tuple = net_context_get_tuple(buf->context);
	if (!tuple) {
		return -EINVAL;
	}

	switch (tuple->ip_proto) {
	case IPPROTO_UDP:
		udp = net_context_get_udp_connection(buf->context);
		if (!net_context_get_receiver_registered(buf->context)) {
			ret = simple_udp_register(udp, tuple->local_port,
#ifdef CONFIG_NETWORKING_WITH_IPV6
				(uip_ip6addr_t *)&tuple->remote_addr->in6_addr,
#else
				(uip_ip4addr_t *)&tuple->remote_addr->in_addr,
#endif
				tuple->remote_port, udp_packet_reply, buf);
			if (!ret) {
				NET_DBG("UDP connection creation failed\n");
				ret = -ENOENT;
				break;
			}
			net_context_set_receiver_registered(buf->context);
		}
		simple_udp_send(buf, udp, buf->data, buf->len);
		ret = 0;
		break;
	case IPPROTO_TCP:
		NET_DBG("TCP not yet supported\n");
		ret = -EINVAL;
		break;
	case IPPROTO_ICMPV6:
		NET_DBG("ICMPv6 not yet supported\n");
		ret = -EINVAL;
		break;
	}

	return ret;
}
示例#4
0
/* Called by application when it wants to receive network data */
struct net_buf *net_receive(struct net_context *context)
{
	struct nano_fifo *rx_queue = net_context_get_queue(context);
	struct net_tuple *tuple;
	int ret = 0;

	tuple = net_context_get_tuple(context);
	if (!tuple) {
		return NULL;
	}

	switch (tuple->ip_proto) {
	case IPPROTO_UDP:
		if (!net_context_get_receiver_registered(context)) {
			struct simple_udp_connection *udp =
				net_context_get_udp_connection(context);

			ret = simple_udp_register(udp, tuple->local_port,
#ifdef CONFIG_NETWORKING_WITH_IPV6
				(uip_ip6addr_t *)&tuple->remote_addr->in6_addr,
#else
				(uip_ip4addr_t *)&tuple->remote_addr->in_addr,
#endif
				tuple->remote_port,
				udp_packet_receive,
				context);
			if (!ret) {
				NET_DBG("UDP connection listener failed\n");
				ret = -ENOENT;
				break;
			}
		}
		net_context_set_receiver_registered(context);
		ret = 0;
		break;
	case IPPROTO_TCP:
		NET_DBG("TCP not yet supported\n");
		ret = -EINVAL;
		break;
	case IPPROTO_ICMPV6:
		NET_DBG("ICMPv6 not yet supported\n");
		ret = -EINVAL;
		break;
	}

	return nano_fifo_get(rx_queue);
}
示例#5
0
/* Switch the ports and addresses and set route and neighbor cache.
 * Returns 1 if packet was sent properly, in this case it is the caller
 * that needs to release the net_buf. If 0 is returned, then uIP stack
 * has released the net_buf already because there was an some net related
 * error when sending the buffer.
 */
static inline int udp_prepare_and_send(struct net_context *context,
				       struct net_buf *buf)
{
#ifdef CONFIG_NETWORKING_WITH_IPV6
	uip_ds6_route_t *route_old, *route_new = NULL;
	uip_ds6_nbr_t *nbr;
#endif
	uip_ipaddr_t tmp;
	uint16_t port;
	uint8_t ret;

	if (uip_len(buf) == 0) {
		/* This is expected as uIP will typically set the
		 * packet length to 0 after receiving it. So we need
		 * to fix the length here. The protocol specific
		 * part is added also here.
		 */
		uip_len(buf) = uip_slen(buf) = uip_appdatalen(buf);
		buf->data = buf->buf + UIP_IPUDPH_LEN;
	}

	port = UIP_UDP_BUF(buf)->srcport;
	UIP_UDP_BUF(buf)->srcport = UIP_UDP_BUF(buf)->destport;
	UIP_UDP_BUF(buf)->destport = port;

	uip_ipaddr_copy(&tmp, &UIP_IP_BUF(buf)->srcipaddr);
	uip_ipaddr_copy(&UIP_IP_BUF(buf)->srcipaddr,
			&UIP_IP_BUF(buf)->destipaddr);
	uip_ipaddr_copy(&UIP_IP_BUF(buf)->destipaddr, &tmp);

#ifdef CONFIG_NETWORKING_WITH_IPV6
	/* The peer needs to be in neighbor cache before route can be added.
	 */
	nbr = uip_ds6_nbr_lookup((uip_ipaddr_t *)&UIP_IP_BUF(buf)->destipaddr);
	if (!nbr) {
		const uip_lladdr_t *lladdr = (const uip_lladdr_t *)&buf->src;
		nbr = uip_ds6_nbr_add(
			(uip_ipaddr_t *)&UIP_IP_BUF(buf)->destipaddr,
			lladdr, 0, NBR_REACHABLE);
		if (!nbr) {
			NET_DBG("Cannot add peer ");
			PRINT6ADDR(&UIP_IP_BUF(buf)->destipaddr);
			PRINT(" to neighbor cache\n");
		}
	}

	/* Temporarily add route to peer, delete the route after
	 * sending the packet. Check if there was already a
	 * route and do not remove it if there was existing
	 * route to this peer.
	 */
	route_old = uip_ds6_route_lookup(&UIP_IP_BUF(buf)->destipaddr);
	if (!route_old) {
		route_new = uip_ds6_route_add(&UIP_IP_BUF(buf)->destipaddr,
					      128,
					      &UIP_IP_BUF(buf)->destipaddr);
		if (!route_new) {
			NET_DBG("Cannot add route to peer ");
			PRINT6ADDR(&UIP_IP_BUF(buf)->destipaddr);
			PRINT("\n");
		}
	}
#endif

	ret = simple_udp_sendto_port(buf,
				     net_context_get_udp_connection(context),
				     buf->data, buf->len,
				     &UIP_IP_BUF(buf)->destipaddr,
				     uip_ntohs(UIP_UDP_BUF(buf)->destport));
	if (!ret) {
		NET_DBG("Packet could not be sent properly.\n");
	}

#ifdef CONFIG_NETWORKING_WITH_IPV6
	if (!route_old && route_new) {
		/* This will also remove the neighbor cache entry */
		uip_ds6_route_rm(route_new);
	}
#endif

	return ret;
}