Esempio n. 1
0
static int icmp_send(uint8_t type, uint8_t code, const void *body,
		size_t body_sz, struct sk_buff *skb) {
	int ret;
	size_t size;

	if (ip_out_ops == NULL) {
		skb_free(skb);
		return -ENOSYS; /* error: not implemented */
	}

	size = sizeof *icmp_hdr(skb) + body_sz;
	assert(ip_out_ops->make_pack != NULL);
	ret = ip_out_ops->make_pack(NULL, NULL, &size, &skb);
	if (ret != 0) {
		skb_free(skb);
		return ret; /* error: see ret */
	}
	else if (size != sizeof *icmp_hdr(skb) + body_sz) {
		skb_free(skb);
		return -EMSGSIZE; /* error: message is too big */
	}

	icmp_build(icmp_hdr(skb), type, code, body, body_sz);
	icmp_set_check_field(icmp_hdr(skb), ip_hdr(skb));

	assert(ip_out_ops->snd_pack != NULL);
	return ip_out_ops->snd_pack(skb);
}
Esempio n. 2
0
static int icmp_rcv(struct sk_buff *skb) {
	struct icmphdr *icmph;
	uint16_t old_check;

	log_debug("%p len %zu", skb, skb->len);
	if (sizeof *icmph > ip_data_length(ip_hdr(skb))) {
		log_error("invalid length (%zu > %zu)",
				sizeof *icmph, ip_data_length(ip_hdr(skb)));
		skb_free(skb);
		return 0; /* error: invalid length */
	}

	if (NULL == skb_declone(skb)) {
		log_error("can't declone data");
		skb_free(skb);
		return -ENOMEM; /* error: can't declone data */
	}

	icmph = icmp_hdr(skb);
	assert(icmph != NULL);

	old_check = icmph->check;
	icmp_set_check_field(icmph, ip_hdr(skb));
	if (old_check != icmph->check) {
		log_error("bad checksum");
		skb_free(skb);
		return 0; /* error: bad checksum */
	}

	switch (icmph->type) {
	default:
		log_error("icmp_rcv: unknown type: %hhu\n", icmph->type);
		break; /* error: unknown type */
	case ICMP_ECHO_REPLY:
	case ICMP_TIMESTAMP_REPLY:
	case ICMP_INFO_REPLY:
		break;
	case ICMP_DEST_UNREACH:
		return icmp_hnd_dest_unreach(icmph, &icmph->body[0].dest_unreach, skb);
	case ICMP_SOURCE_QUENCH:
		return icmp_hnd_source_quench(icmph,
				&icmph->body[0].source_quench, skb);
	case ICMP_REDIRECT:
	case ICMP_TIME_EXCEED:
	case ICMP_INFO_REQUEST:
		break; /* error: not implemented */
	case ICMP_ECHO_REQUEST:
		return icmp_hnd_echo_request(icmph, &icmph->body[0].echo, skb);
	case ICMP_PARAM_PROB:
		return icmp_hnd_param_prob(icmph, &icmph->body[0].param_prob, skb);
	case ICMP_TIMESTAMP_REQUEST:
		return icmp_hnd_timestamp_request(icmph,
				&icmph->body[0].timestamp, skb);
	}

	skb_free(skb);
	return 0;
}