Example #1
0
unsigned char icmp_valid(unsigned char *packet, echo_request_t req, reply_response_t *res) {
  // Reference to where the ICMP section starts
  unsigned char *icmp_start_ptr = packet;

  // Is it an echo reply (or time to live exceeded) with code = 0?
  unsigned char icmp_type;
  CONSUME_BYTES(packet, &icmp_type, sizeof(icmp_type));
  if (icmp_type != 0 && icmp_type != 11)
    return 0;
  unsigned char code;
  CONSUME_BYTES(packet, &code, sizeof(code));
  if (code != 0)
    return 0;

  // Is the checksum for the ICMP header correct?
  unsigned short checksum;
  unsigned char *checksum_ptr = packet;
  CONSUME_BYTES(packet, &checksum, sizeof(checksum));
  checksum = ntohs(checksum);
  // Go back to the checksum start and zero it out in order to validate the message
  memset(checksum_ptr, 0, sizeof(checksum));
  // Calculate the checksum with the info we have
  unsigned short calculated_checksum = in_cksum((short unsigned int *)icmp_start_ptr, res->ip_packet_length - 20);
  calculated_checksum = ntohs(calculated_checksum);
  if (checksum != calculated_checksum)
    return 0;

  // If time to live was exceeded but the checksum is valid, we let the user
  // know about the TTL exceeded, otherwise we discard the packet on the
  // `if` above
  if (icmp_type == 11) {
    res->result = REPLY_TTL_EXCEEDED;
    return 1;
  }

  // Identifier matches?
  unsigned short identifier;
  CONSUME_BYTES(packet, &identifier, sizeof(identifier));
  identifier = ntohs(identifier);
  if (identifier != req.identifier) {
    return 0;
  }

  // Sequence number matches?
  unsigned short sequence_number;
  CONSUME_BYTES(packet, &sequence_number, sizeof(sequence_number));
  sequence_number = ntohs(sequence_number);
  return sequence_number == req.sequence_number;
}
Example #2
0
static ssize_t
strdata_from_buf(uint8_t *buf, size_t nbytes, size_t n, ...)
{
	const char **cur;
	uint16_t magic;
	ssize_t avail;
	size_t slen;
	va_list ap;

#define BUF_WALK(bytes)  \
	do {                 \
		buf += bytes;    \
		avail -= bytes; \
		                 \
		if (avail < 0)  \
			return -1;   \
	} while (0)

#define CONSUME_BYTES(nb)     \
	({                        \
		uint8_t *obuf = buf;  \
		BUF_WALK(nb);         \
		obuf;                 \
	})

#define CONSUME_TYPE(type)           \
	*((type *) ({                    \
		CONSUME_BYTES(sizeof(type)); \
	}))

	avail = nbytes;
	va_start(ap, n);

	while (n--) {
		cur = va_arg(ap, const char **);
		*cur = NULL;

		slen  = CONSUME_TYPE(size_t);
		*cur  = (char *) CONSUME_BYTES(slen);
		magic = CONSUME_TYPE(uint16_t);

		if (magic != IPC_MAGIC) {
			*cur = NULL;
			return -1;
		}

		/* null-terminate the string (this is a little hack) */
		*(buf - 2) = '\0';
		*cur = s_strdup(*cur);
	}

	va_end(ap);

#undef CONSUME_TYPE
#undef CONSUME_BYTES
#undef BUF_WALK

	return nbytes - avail;
}
Example #3
0
unsigned char ipv4_valid(unsigned char *packet, echo_request_t req, reply_response_t *res) {
  // Reference to where the IP section starts
  unsigned char *ip_start_ptr = packet;

  // Check if is V4 and has 20 bytes on the header
  char ip_version_and_header_length;
  CONSUME_BYTES(packet, &ip_version_and_header_length, sizeof(ip_version_and_header_length));
  if (ip_version_and_header_length != 0x45)
    return 0;

  // Move forward 1 byte that represents some flags we don't care about
  packet += 1;

  // Total length of the packet
  CONSUME_BYTES(packet, &res->ip_packet_length, sizeof(res->ip_packet_length));
  res->ip_packet_length = ntohs(res->ip_packet_length);

  // Move forward some bytes that represents some stuff we don't care about
  packet += 4; // 2 for packet ID, 2 for flags and offset

  // Extract ttl
  CONSUME_BYTES(packet, &res->ttl, sizeof(res->ttl));

  // Check if the protocol is ICMP
  unsigned char protocol;
  CONSUME_BYTES(packet, &protocol, sizeof(protocol));
  if (protocol != 1)
    return 0;

  // Is the checksum for the IP header correct?
  unsigned short checksum;
  unsigned char *checksum_ptr = packet;
  CONSUME_BYTES(packet, &checksum, sizeof(checksum));
  checksum = ntohs(checksum);
  // Go back to the checksum start and zero it out in order to validate the message
  memset(checksum_ptr, 0, sizeof(checksum));
  // Calculate the checksum with the info we have
  unsigned short calculated_checksum = in_cksum((short unsigned int *)ip_start_ptr, IP_HEADER_LEN);
  calculated_checksum = ntohs(calculated_checksum);

  if (checksum != calculated_checksum)
    return 0;

  // Source IP
  CONSUME_BYTES(packet, &res->source_ip, IP_ADDR_LEN * sizeof(unsigned char));

  // Target IP (us)
  unsigned char target_ip[IP_ADDR_LEN];
  CONSUME_BYTES(packet, target_ip, IP_ADDR_LEN * sizeof(unsigned char));
  // Does the IP match?
  unsigned char i;
  for (i = 0; i < IP_ADDR_LEN; i++) {
    if (target_ip[i] != req.local_ip[i])
      return 0;
  }

  return 1;
}
Example #4
0
unsigned char ethernet_valid(unsigned char *packet, echo_request_t req) {
  // Is the packet targeted to us?
  unsigned char i;
  for (i = 0; i < MAC_ADDR_LEN; i++) {
    if (packet[i] != req.local_mac[i])
      return 0;
  }

  // Move past the 2 MAC addresses on the ethernet header
  packet += 2 * MAC_ADDR_LEN;

  // Check if the packet type is an IPv4
  short ether_type;
  CONSUME_BYTES(packet, &ether_type, sizeof(ether_type));
  return ether_type == 8;
}