71 lines
1.5 KiB
C
71 lines
1.5 KiB
C
#include "internal/icmp_packet_internal.h"
|
|
#include "internal/icmp_packet.h"
|
|
#include <netinet/in.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
|
|
/* Minimum IP header size */
|
|
#define MIN_IP_HEADER_SIZE 20
|
|
|
|
/* Forward declarations */
|
|
static int validate_ip_header(const struct ip_header *hdr, size_t buffer_len);
|
|
static size_t extract_ip_header_length(uint8_t version_ihl);
|
|
/* -------------------- */
|
|
|
|
int
|
|
icmp_parse_ip_header(const void *buffer, size_t buffer_len, uint8_t *ttl,
|
|
struct in_addr *src_addr, size_t *ip_hdr_len,
|
|
struct in_addr *dst_addr, uint8_t *protocol)
|
|
{
|
|
const struct ip_header *h;
|
|
size_t ihl_bytes;
|
|
|
|
if (buffer_len < MIN_IP_HEADER_SIZE)
|
|
return -1;
|
|
|
|
h = (const struct ip_header *)buffer;
|
|
ihl_bytes = extract_ip_header_length(h->version_ihl);
|
|
|
|
if (0 != validate_ip_header(h, buffer_len))
|
|
return -1;
|
|
|
|
if (ttl)
|
|
*ttl = h->ttl;
|
|
if (src_addr)
|
|
src_addr->s_addr = h->saddr;
|
|
if (dst_addr)
|
|
dst_addr->s_addr = h->daddr;
|
|
if (protocol)
|
|
*protocol = h->protocol;
|
|
if (ip_hdr_len)
|
|
*ip_hdr_len = ihl_bytes;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
validate_ip_header(const struct ip_header *hdr, size_t buffer_len)
|
|
{
|
|
uint8_t ihl;
|
|
size_t header_len;
|
|
|
|
if (4 != (hdr->version_ihl >> 4))
|
|
return -1;
|
|
|
|
ihl = hdr->version_ihl & 0x0F;
|
|
if (ihl < 5)
|
|
return -1;
|
|
|
|
header_len = (size_t)(ihl << 2);
|
|
if (header_len > buffer_len)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static size_t
|
|
extract_ip_header_length(uint8_t version_ihl)
|
|
{
|
|
return (size_t)((version_ihl & 0x0F) << 2);
|
|
}
|