Esempio n. 1
0
void net_send_icmp(uint8_t type, uint8_t code, uint8_t *body,
		uint16_t body_length) {
	/**
	 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 |     Type      |     Code      |          Checksum             |
	 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 |                                                               |
	 +                         Message Body                          +
	 |                                                               |
	 */

	uint8_t buf[2];
	CHECK_SP("net_send_icmp: ");
	buf[0] = type;
	buf[1] = code;
	net_send_data(buf, 2);
	calc_checksum(buf, 2);

	net_send_dummy_checksum();

	net_send_data(body, body_length);
	calc_checksum(body, body_length);
}
Esempio n. 2
0
void net_send_icmp_start(uint8_t type, uint8_t code) {
	/**
	 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 |     Type      |     Code      |          Checksum             |
	 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 |                                                               |
	 +                         Message Body                          +
	 |                                                               |
	 */

	uint8_t buf[2];
	CHECK_SP("net_send_icmp_start: ");

	buf[0] = type;
	buf[1] = code;
	net_send_data(buf, 2);
	calc_checksum(buf, 2);

	net_send_dummy_checksum();
}
Esempio n. 3
0
/* Prepare DHCPv4 Message request and send it to peer */
static void send_request(struct net_if *iface, bool renewal)
{
	struct net_buf *buf;

	buf = prepare_message(iface, DHCPV4_MSG_TYPE_REQUEST);
	if (!buf) {
		goto fail;
	}

	if (!add_server_id(buf) ||
	    !add_req_ipaddr(buf) ||
	    !add_end(buf)) {
		goto fail;
	}

	setup_header(buf);

	if (net_send_data(buf) < 0) {
		goto fail;
	}

	if (renewal) {
		iface->dhcpv4.state = NET_DHCPV4_RENEWAL;
	} else {
		iface->dhcpv4.state = NET_DHCPV4_REQUEST;
	}

	iface->dhcpv4.attempts++;

	k_delayed_work_init(&iface->dhcpv4_timeout, dhcpv4_timeout);
	k_delayed_work_submit(&iface->dhcpv4_timeout, get_dhcpv4_timeout());

	return;

fail:
	NET_DBG("Message preparation failed");

	if (!buf) {
		net_nbuf_unref(buf);
	}
}
Esempio n. 4
0
/* Prepare DHCPv4 Discover message and broadcast it */
static void send_discover(struct net_if *iface)
{
	struct net_buf *buf;

	iface->dhcpv4.xid++;

	buf = prepare_message(iface, DHCPV4_MSG_TYPE_DISCOVER);
	if (!buf) {
		goto fail;
	}

	if (!add_req_options(buf) ||
	    !add_end(buf)) {
		goto fail;
	}

	setup_header(buf);

	if (net_send_data(buf) < 0) {
		goto fail;
	}

	iface->dhcpv4.state = NET_DHCPV4_DISCOVER;

	k_delayed_work_init(&iface->dhcpv4_timeout, dhcpv4_timeout);
	k_delayed_work_submit(&iface->dhcpv4_timeout, get_dhcpv4_timeout());

	return;

fail:
	NET_DBG("Message preparation failed");

	if (!buf) {
		net_nbuf_unref(buf);
	}
}
Esempio n. 5
0
static bool send_iface(struct net_if *iface, int val, bool expect_fail)
{
	static u8_t data[] = { 't', 'e', 's', 't', '\0' };
	struct net_pkt *pkt;
	int ret;

	pkt = net_pkt_get_reserve_tx(0, K_FOREVER);
	net_pkt_set_iface(pkt, iface);

	net_pkt_append_all(pkt, sizeof(data), data, K_FOREVER);

	ret = net_send_data(pkt);
	if (!expect_fail && ret < 0) {
		DBG("Cannot send test packet (%d)\n", ret);
		return false;
	}

	if (!expect_fail && k_sem_take(&wait_data, WAIT_TIME)) {
		DBG("Timeout while waiting interface %d data\n", val);
		return false;
	}

	return true;
}
Esempio n. 6
0
void handle_icmp(uint8_t *macSource, uint8_t *sourceAddr, uint8_t *destIPAddr,
		uint16_t length, DATA_CB dataCb, void *priv) {
	/**
	 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 |     Type      |     Code      |          Checksum             |
	 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 |                                                               |
	 +                         Message Body                          +
	 |                                                               |
	 */

	/* Allocate just enough data to handle the type, code, and checksum fields */
	uint8_t buf[4];
	uint8_t type;
	CHECK_SP("handle_icmp: ");
#ifdef DEBUG_ICMP
	PRINT_SP("handle_icmp: ");
#endif

	dataCb(buf, 4, priv);

	type = buf[0];

#ifdef DEBUG_ICMP
	debug_puts("Payload size: ");
	debug_puthex(length);
	debug_nl();
	debug_puts("ICMP Type:");
	debug_puthex(type);
	debug_nl();
#endif

	/*calc_checksum(payload, 4);

	 uint16_t r = dataCb(payload, length - 4, priv);

	 calc_checksum(payload, length - 4);

	 if (checksum != 0xFFFF) {
	 debug_puts("Checksum error");
	 debug_nl();
	 return;
	 }*/

	if (net_state != STATE_IDLE && type != ICMP_TYPE_NEIGHBOR_SOLICITATION
			&& type != ICMP_TYPE_NEIGHBOR_ADVERTISMENT) {
		debug_puts("Not in a state to receive ICMP message");
		debug_nl();
		return;
	}

	switch (type) {
	case ICMP_TYPE_NEIGHBOR_SOLICITATION:
		/* First 4 bytes are 'reserved', we ignore them. but must read them */
		dataCb(buf, 4, priv);

		/* Next 16 bytes are the target address. We assume it's one of our addresses as it was passed to us
		 by handle_ipv6()
		 */

		/* We only reply if there is a source link-layer address option */
		if (length > 20) {
			uint8_t addr[16];

			/* Read address*/
			dataCb(addr, 16, priv);

			/* Read option 'header' */
			dataCb(buf, 2, priv);
			if (buf[0] == 0x01) {
				uint8_t mac_addr[6];

				dataCb(mac_addr, 6, priv);
				/* We now got the link-layer address and IPv6 address of someone, store it */
				register_mac_addr(mac_addr, sourceAddr);
				send_neighbor_advertisment(mac_addr, addr, sourceAddr, addr);
			}
		}
		break;
	case ICMP_TYPE_NEIGHBOR_ADVERTISMENT: {
		/* We ignore first 4 bytes */
		uint8_t received_addr[16];
		dataCb(buf, 4, priv);
		dataCb(received_addr, 16, priv);
		if (net_state == STATE_DAD) {
			uint8_t addr[16];

			net_get_address(ADDRESS_STORE_LINK_LOCAL_OFFSET, addr);
			if (memcmp(received_addr, addr, 16) == 0) {
				net_state = STATE_INVALID;
				return;
			}
		}

		register_mac_addr(macSource, received_addr);
		net_state = STATE_IDLE;
	}
		break;
	case ICMP_TYPE_ECHO_REQUEST:
		if (length >= 8) {
			dataCb(buf, 4, priv);
			uint16_t id = (buf[0] << 8) | buf[1];
			uint16_t seqNo = (buf[2] << 8) | buf[3];
			struct ipv6_packet_arg arg;
			arg.dst_mac_addr = null_mac;
			arg.dst_ipv6_addr = sourceAddr;
			arg.src_ipv6_addr = destIPAddr;
			//arg.payload_length = SIZE_ICMP_HEADER + length;
			arg.protocol = PROTO_ICMP;

			net_start_ipv6_packet(&arg);
			net_send_icmp_start(ICMP_TYPE_ECHO_REPLY, 0);
			net_send_data(buf, 4);
			calc_checksum(buf, 4);
			uint16_t count;
			length -= 8;
			while( (count=dataCb(buf, 4, priv)) > 0 && length > 0) {
				net_send_data(buf, count);
				calc_checksum(buf, count);
			}
			//net_send_icmp(ICMP_TYPE_ECHO_REPLY, 0, payload, length);
			net_end_ipv6_packet();
		}
		break;
	case ICMP_TYPE_ROUTER_ADVERTISMENT:
		/* Ignore first 12 bytes, as we are only interested in
		 addresses. Next, loop through the options in the payload
		 */
	{
		if( length > 140 ) {
			debug_puts("Lengths exceeds 140 Bytes, ignore router advertisment in order to avoid trouble");
			debug_nl();
			return;
		}
		uint8_t payload[length-4];
		CHECK_SP("handle_icmp, ICMP_TYPE_ROUTER_ADVERTISMENT: ");
		dataCb(payload, length-4, priv);
		uint8_t *c = payload + 12;
		while (c < payload + length - 4) {
			if (c[0] == 3) {
				uint8_t prefixLength = c[2];
				/* Prefix starts at offset 16 */
				uint8_t buf[16];
				net_get_address(ADDRESS_STORE_MAIN_OFFSET, buf);
				if (buf[0] == 0x00) {
					// null_mac as destination means link-local (go figure)
					routing_table_add(c + 16, prefixLength / 8, null_mac);

					// Default route
					routing_table_add(unspec_addr, 0, macSource);
					assign_address_from_prefix(c + 16, prefixLength);
					//mem_write(default_route_mac_id, 0, macSource, 6);
				} else {

				}
			}
			c += c[1] * 8;
		}
	}
		break;
	}
}