summaryrefslogtreecommitdiff
path: root/src/packet/packet.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/packet/packet.cpp')
-rw-r--r--src/packet/packet.cpp117
1 files changed, 84 insertions, 33 deletions
diff --git a/src/packet/packet.cpp b/src/packet/packet.cpp
index 029258a..19c4a51 100644
--- a/src/packet/packet.cpp
+++ b/src/packet/packet.cpp
@@ -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_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);
// 传输层
@@ -133,6 +134,8 @@ static inline const char *layer_type_to_str(enum layer_type type)
return "IPV4";
case LAYER_TYPE_IPV6:
return "IPV6";
+ case LAYER_TYPE_IPAH:
+ return "IPAH";
case LAYER_TYPE_GRE:
return "GRE";
case LAYER_TYPE_UDP:
@@ -958,7 +961,21 @@ static inline const char *parse_ipv6(struct packet *pkt, const char *data, uint1
return data;
}
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))
{
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);
}
+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)
{
#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)
{
+ // TODO
+ // check V1 or V2
+
// GTP1U_PORT 2152
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)
{
// L2TP_DPORT 1701
@@ -1209,6 +1288,8 @@ static inline const char *parse_l4(struct packet *pkt, uint8_t next_proto, const
{
switch (next_proto)
{
+ case IPPROTO_AH:
+ return parse_auth(pkt, data, len);
case IPPROTO_TCP:
return parse_tcp(pkt, data, len);
case IPPROTO_UDP:
@@ -1294,6 +1375,8 @@ void packet_print_str(const struct packet *pkt)
case LAYER_TYPE_IPV6:
used = ipv6_hdr_to_str((const struct ip6_hdr *)layer->hdr_ptr, buffer, sizeof(buffer));
break;
+ case LAYER_TYPE_IPAH:
+ break;
case LAYER_TYPE_GRE:
break;
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 -1 : not found
int packet_get_innermost_tuple2(const struct packet *pkt, struct tuple2 *tuple)