Add support for parsing IP Authentication Header
This commit is contained in:
@@ -27,22 +27,23 @@ enum layer_type
|
|||||||
// L3 -- network layer
|
// L3 -- network layer
|
||||||
LAYER_TYPE_IPV4 = 1 << 8,
|
LAYER_TYPE_IPV4 = 1 << 8,
|
||||||
LAYER_TYPE_IPV6 = 1 << 9,
|
LAYER_TYPE_IPV6 = 1 << 9,
|
||||||
LAYER_TYPE_L3 = (LAYER_TYPE_IPV4 | LAYER_TYPE_IPV6),
|
LAYER_TYPE_IPAH = 1 << 10,
|
||||||
|
LAYER_TYPE_L3 = (LAYER_TYPE_IPV4 | LAYER_TYPE_IPV6 | LAYER_TYPE_IPAH),
|
||||||
|
|
||||||
// L3 -- tunnel
|
// L3 -- tunnel
|
||||||
LAYER_TYPE_GRE = 1 << 10,
|
LAYER_TYPE_GRE = 1 << 11,
|
||||||
LAYER_TYPE_L3_TUN = (LAYER_TYPE_GRE),
|
LAYER_TYPE_L3_TUN = (LAYER_TYPE_GRE),
|
||||||
|
|
||||||
// L4 -- transport layer
|
// L4 -- transport layer
|
||||||
LAYER_TYPE_UDP = 1 << 11,
|
LAYER_TYPE_UDP = 1 << 12,
|
||||||
LAYER_TYPE_TCP = 1 << 12,
|
LAYER_TYPE_TCP = 1 << 13,
|
||||||
LAYER_TYPE_ICMP = 1 << 13,
|
LAYER_TYPE_ICMP = 1 << 14,
|
||||||
LAYER_TYPE_ICMP6 = 1 << 14,
|
LAYER_TYPE_ICMP6 = 1 << 15,
|
||||||
LAYER_TYPE_L4 = (LAYER_TYPE_UDP | LAYER_TYPE_TCP | LAYER_TYPE_ICMP | LAYER_TYPE_ICMP6),
|
LAYER_TYPE_L4 = (LAYER_TYPE_UDP | LAYER_TYPE_TCP | LAYER_TYPE_ICMP | LAYER_TYPE_ICMP6),
|
||||||
|
|
||||||
// L4 -- tunnel
|
// L4 -- tunnel
|
||||||
LAYER_TYPE_VXLAN = 1 << 15,
|
LAYER_TYPE_VXLAN = 1 << 16,
|
||||||
LAYER_TYPE_GTPV1_U = 1 << 16,
|
LAYER_TYPE_GTPV1_U = 1 << 17,
|
||||||
|
|
||||||
// ALL
|
// ALL
|
||||||
LAYER_TYPE_ALL = (LAYER_TYPE_L2 | LAYER_TYPE_L2_TUN | LAYER_TYPE_L3 | LAYER_TYPE_L3_TUN | LAYER_TYPE_L4 | LAYER_TYPE_VXLAN | LAYER_TYPE_GTPV1_U),
|
LAYER_TYPE_ALL = (LAYER_TYPE_L2 | LAYER_TYPE_L2_TUN | LAYER_TYPE_L3 | LAYER_TYPE_L3_TUN | LAYER_TYPE_L4 | LAYER_TYPE_VXLAN | LAYER_TYPE_GTPV1_U),
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ static inline uint8_t ipv4_hdr_get_version(const struct ip *hdr)
|
|||||||
return hdr->ip_v;
|
return hdr->ip_v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IP Options are included in the hdr_len field
|
||||||
static inline uint8_t ipv4_hdr_get_hdr_len(const struct ip *hdr)
|
static inline uint8_t ipv4_hdr_get_hdr_len(const struct ip *hdr)
|
||||||
{
|
{
|
||||||
return hdr->ip_hl << 2;
|
return hdr->ip_hl << 2;
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ static inline const char *parse_mpls(struct packet *pkt, const char *data, uint1
|
|||||||
// 网络层
|
// 网络层
|
||||||
static inline const char *parse_ipv4(struct packet *pkt, const char *data, uint16_t len);
|
static inline const char *parse_ipv4(struct packet *pkt, const char *data, uint16_t len);
|
||||||
static inline const char *parse_ipv6(struct packet *pkt, const char *data, uint16_t len);
|
static inline const char *parse_ipv6(struct packet *pkt, const char *data, uint16_t len);
|
||||||
|
static inline const char *parse_auth(struct packet *pkt, const char *data, uint16_t len);
|
||||||
// 网络层 -- 隧道
|
// 网络层 -- 隧道
|
||||||
static inline const char *parse_gre(struct packet *pkt, const char *data, uint16_t len);
|
static inline const char *parse_gre(struct packet *pkt, const char *data, uint16_t len);
|
||||||
// 传输层
|
// 传输层
|
||||||
@@ -133,6 +134,8 @@ static inline const char *layer_type_to_str(enum layer_type type)
|
|||||||
return "IPV4";
|
return "IPV4";
|
||||||
case LAYER_TYPE_IPV6:
|
case LAYER_TYPE_IPV6:
|
||||||
return "IPV6";
|
return "IPV6";
|
||||||
|
case LAYER_TYPE_IPAH:
|
||||||
|
return "IPAH";
|
||||||
case LAYER_TYPE_GRE:
|
case LAYER_TYPE_GRE:
|
||||||
return "GRE";
|
return "GRE";
|
||||||
case LAYER_TYPE_UDP:
|
case LAYER_TYPE_UDP:
|
||||||
@@ -958,7 +961,21 @@ static inline const char *parse_ipv6(struct packet *pkt, const char *data, uint1
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
struct ip6_ext *ext = (struct ip6_ext *)next_hdr_ptr;
|
struct ip6_ext *ext = (struct ip6_ext *)next_hdr_ptr;
|
||||||
uint16_t skip_len = ext->ip6e_len * 8 + 8;
|
uint16_t skip_len = 0;
|
||||||
|
if (next_proto == IPPROTO_AH)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* https://datatracker.ietf.org/doc/html/rfc4302#section-2
|
||||||
|
* For IPv6, the total length of the header must be a multiple of 8-octet units.
|
||||||
|
* (Note that although IPv6 [DH98] characterizes AH as an extension header,
|
||||||
|
* its length is measured in 32-bit words, not the 64-bit words used by other IPv6 extension headers.)
|
||||||
|
*/
|
||||||
|
skip_len = ext->ip6e_len * 4 + 8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
skip_len = ext->ip6e_len * 8 + 8;
|
||||||
|
}
|
||||||
if (unlikely(skip_len > pld_len))
|
if (unlikely(skip_len > pld_len))
|
||||||
{
|
{
|
||||||
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_TYPE_IPV6);
|
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_TYPE_IPV6);
|
||||||
@@ -982,6 +999,59 @@ static inline const char *parse_ipv6(struct packet *pkt, const char *data, uint1
|
|||||||
return parse_l4(pkt, next_proto, layer->pld_ptr, layer->pld_len);
|
return parse_l4(pkt, next_proto, layer->pld_ptr, layer->pld_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline const char *parse_auth(struct packet *pkt, const char *data, uint16_t len)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* https://datatracker.ietf.org/doc/html/rfc4302#section-2
|
||||||
|
* For IPv4: AH not IPv4 option, as an single layer
|
||||||
|
* For IPv6: AH as IPv6 extension header
|
||||||
|
*
|
||||||
|
* AH Format
|
||||||
|
*
|
||||||
|
* 0 1 2 3
|
||||||
|
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
* | Next Header | Payload Len | RESERVED |
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
* | Security Parameters Index (SPI) |
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
* | Sequence Number Field |
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
* | |
|
||||||
|
* + Integrity Check Value-ICV (variable) |
|
||||||
|
* | |
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (unlikely(len < 12))
|
||||||
|
{
|
||||||
|
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_TYPE_IPAH);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* https://datatracker.ietf.org/doc/html/rfc4302#section-2
|
||||||
|
* For IPv4, This 8-bit field specifies the length of AH in 32-bit words (4-byte units), minus "2".
|
||||||
|
* Thus, for example, if an integrity algorithm yields a 96-bit authentication value,
|
||||||
|
* this length field will be "4" (3 32-bit word fixed fields plus 3 32-bit words for the ICV, minus 2).
|
||||||
|
*/
|
||||||
|
uint8_t next_proto = ((const uint8_t *)data)[0];
|
||||||
|
uint16_t hdr_len = ((const uint8_t *)data)[1] * 4 + 8;
|
||||||
|
if (unlikely(len < hdr_len))
|
||||||
|
{
|
||||||
|
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_TYPE_IPAH);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct packet_layer *layer = get_free_layer(pkt);
|
||||||
|
if (unlikely(layer == NULL))
|
||||||
|
{
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
SET_LAYER(pkt, layer, LAYER_TYPE_IPAH, hdr_len, data, len, 0);
|
||||||
|
|
||||||
|
return parse_l4(pkt, next_proto, layer->pld_ptr, layer->pld_len);
|
||||||
|
}
|
||||||
|
|
||||||
static inline const char *parse_gre(struct packet *pkt, const char *data, uint16_t len)
|
static inline const char *parse_gre(struct packet *pkt, const char *data, uint16_t len)
|
||||||
{
|
{
|
||||||
#define GRE_PRO_IPV4 (0x0800)
|
#define GRE_PRO_IPV4 (0x0800)
|
||||||
@@ -1042,10 +1112,19 @@ static inline const char *parse_udp(struct packet *pkt, const char *data, uint16
|
|||||||
|
|
||||||
if (udp_hdr_get_dst_port(hdr) == 2152 || udp_hdr_get_src_port(hdr) == 2152)
|
if (udp_hdr_get_dst_port(hdr) == 2152 || udp_hdr_get_src_port(hdr) == 2152)
|
||||||
{
|
{
|
||||||
|
// TODO
|
||||||
|
// check V1 or V2
|
||||||
|
|
||||||
// GTP1U_PORT 2152
|
// GTP1U_PORT 2152
|
||||||
return parse_gtpv1_u(pkt, layer->pld_ptr, layer->pld_len);
|
return parse_gtpv1_u(pkt, layer->pld_ptr, layer->pld_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (udp_hdr_get_dst_port(hdr) == 2123 || udp_hdr_get_src_port(hdr) == 2123)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
// GTP-C - GTP control 2123
|
||||||
|
}
|
||||||
|
|
||||||
if (udp_hdr_get_dst_port(hdr) == 1701)
|
if (udp_hdr_get_dst_port(hdr) == 1701)
|
||||||
{
|
{
|
||||||
// L2TP_DPORT 1701
|
// L2TP_DPORT 1701
|
||||||
@@ -1209,6 +1288,8 @@ static inline const char *parse_l4(struct packet *pkt, uint8_t next_proto, const
|
|||||||
{
|
{
|
||||||
switch (next_proto)
|
switch (next_proto)
|
||||||
{
|
{
|
||||||
|
case IPPROTO_AH:
|
||||||
|
return parse_auth(pkt, data, len);
|
||||||
case IPPROTO_TCP:
|
case IPPROTO_TCP:
|
||||||
return parse_tcp(pkt, data, len);
|
return parse_tcp(pkt, data, len);
|
||||||
case IPPROTO_UDP:
|
case IPPROTO_UDP:
|
||||||
@@ -1294,6 +1375,8 @@ void packet_print_str(const struct packet *pkt)
|
|||||||
case LAYER_TYPE_IPV6:
|
case LAYER_TYPE_IPV6:
|
||||||
used = ipv6_hdr_to_str((const struct ip6_hdr *)layer->hdr_ptr, buffer, sizeof(buffer));
|
used = ipv6_hdr_to_str((const struct ip6_hdr *)layer->hdr_ptr, buffer, sizeof(buffer));
|
||||||
break;
|
break;
|
||||||
|
case LAYER_TYPE_IPAH:
|
||||||
|
break;
|
||||||
case LAYER_TYPE_GRE:
|
case LAYER_TYPE_GRE:
|
||||||
break;
|
break;
|
||||||
case LAYER_TYPE_UDP:
|
case LAYER_TYPE_UDP:
|
||||||
@@ -1320,38 +1403,6 @@ void packet_print_str(const struct packet *pkt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void packet_print_table(const struct packet *pkt)
|
|
||||||
{
|
|
||||||
if (pkt == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("packet: %p, data_ptr: %p, data_len: %u, trim_len: %u, layers_used: %u, layers_size: %u\n",
|
|
||||||
pkt, pkt->data_ptr, pkt->data_len, pkt->trim_len,
|
|
||||||
pkt->layers_used, pkt->layers_size);
|
|
||||||
printf("+------------+------------+------------+------------+------------+------------+------------+\n");
|
|
||||||
printf("| %-10s | %-10s | %-10s | %-10s | %-10s | %-10s | %-10s |\n",
|
|
||||||
"index", "type", "hdr ptr", "hdr offset", "hdr len", "pld ptr", "pld len");
|
|
||||||
printf("+------------+------------+------------+------------+------------+------------+------------+\n");
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < pkt->layers_used; i++)
|
|
||||||
{
|
|
||||||
const struct packet_layer *layer = &pkt->layers[i];
|
|
||||||
printf("| %-10u | %-10s | %-10p | %-10u | %-10u | %-10p | %-10u |\n",
|
|
||||||
i, layer_type_to_str(layer->type),
|
|
||||||
layer->hdr_ptr, layer->hdr_offset, layer->hdr_len,
|
|
||||||
layer->pld_ptr, layer->pld_len);
|
|
||||||
printf("+------------+------------+------------+------------+------------+------------+------------+\n");
|
|
||||||
}
|
|
||||||
printf("data: ");
|
|
||||||
for (uint16_t i = 0; i < pkt->data_len; i++)
|
|
||||||
{
|
|
||||||
printf("0x%02x, ", (uint8_t)pkt->data_ptr[i]);
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// return 0 : found
|
// return 0 : found
|
||||||
// return -1 : not found
|
// return -1 : not found
|
||||||
int packet_get_innermost_tuple2(const struct packet *pkt, struct tuple2 *tuple)
|
int packet_get_innermost_tuple2(const struct packet *pkt, struct tuple2 *tuple)
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ struct packet
|
|||||||
// return innermost payload
|
// return innermost payload
|
||||||
const char *packet_parse(struct packet *pkt, const char *data, uint16_t len);
|
const char *packet_parse(struct packet *pkt, const char *data, uint16_t len);
|
||||||
void packet_print_str(const struct packet *pkt);
|
void packet_print_str(const struct packet *pkt);
|
||||||
void packet_print_table(const struct packet *pkt);
|
|
||||||
|
|
||||||
// direction 1: E2I
|
// direction 1: E2I
|
||||||
// direction 0: I2E
|
// direction 0: I2E
|
||||||
|
|||||||
@@ -108,13 +108,10 @@ function preprocess_tshark_ouput() {
|
|||||||
":data" ""
|
":data" ""
|
||||||
":sctp:m3ua" ""
|
":sctp:m3ua" ""
|
||||||
":sctp" ""
|
":sctp" ""
|
||||||
":teredo:ipv6:udp" ""
|
|
||||||
":teredo:ipv6:tcp" ""
|
|
||||||
":teredo:ipv6:icmpv6" ""
|
|
||||||
":teredo:ipv6:gre:ip:udp" ""
|
|
||||||
":igmp" ""
|
":igmp" ""
|
||||||
":icmp:ip:tcp" ":icmp"
|
":icmp:ip:tcp" ":icmp"
|
||||||
":pwethheuristic:pwethnocw" ""
|
":pwethheuristic:pwethnocw" ""
|
||||||
|
":ospf" ""
|
||||||
)
|
)
|
||||||
for ((i = 0; i < ${#kv_array[@]}; i += 2)); do
|
for ((i = 0; i < ${#kv_array[@]}; i += 2)); do
|
||||||
key=${kv_array[i]}
|
key=${kv_array[i]}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ static int ipv6_proto_to_str(const struct packet_layer *ipv6_layer, char *buff,
|
|||||||
used += snprintf(buff + used, size - used, ":ipv6.routing");
|
used += snprintf(buff + used, size - used, ":ipv6.routing");
|
||||||
break;
|
break;
|
||||||
case IPPROTO_AH:
|
case IPPROTO_AH:
|
||||||
used += snprintf(buff + used, size - used, ":ipv6.ah");
|
used += snprintf(buff + used, size - used, ":ah");
|
||||||
break;
|
break;
|
||||||
case IPPROTO_DSTOPTS:
|
case IPPROTO_DSTOPTS:
|
||||||
used += snprintf(buff + used, size - used, ":ipv6.dstopts");
|
used += snprintf(buff + used, size - used, ":ipv6.dstopts");
|
||||||
@@ -79,6 +79,9 @@ static int packet_proto_to_str(const struct packet *pkt, char *buff, int size)
|
|||||||
case LAYER_TYPE_IPV6:
|
case LAYER_TYPE_IPV6:
|
||||||
used += ipv6_proto_to_str(layer, buff + used, size - used);
|
used += ipv6_proto_to_str(layer, buff + used, size - used);
|
||||||
break;
|
break;
|
||||||
|
case LAYER_TYPE_IPAH:
|
||||||
|
used += snprintf(buff + used, size - used, "ah");
|
||||||
|
break;
|
||||||
case LAYER_TYPE_GRE:
|
case LAYER_TYPE_GRE:
|
||||||
used += snprintf(buff + used, size - used, "gre");
|
used += snprintf(buff + used, size - used, "gre");
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user