Add support for parsing PPP headers with variable lengths

This commit is contained in:
luwenpeng
2024-05-31 14:35:58 +08:00
parent 2d958dbe07
commit f3b92a8a15
4 changed files with 226 additions and 43 deletions

View File

@@ -771,22 +771,95 @@ static inline const char *parse_ether(struct packet *pkt, const char *data, uint
return parse_l3(pkt, next_proto, layer->pld_ptr, layer->pld_len);
}
static inline int next_proto_is_ppp(uint16_t next_proto)
{
// /usr/include/linux/ppp_defs.h.html
switch (next_proto)
{
case PPP_IP: /* Internet Protocol */
case PPP_AT: /* AppleTalk Protocol */
case PPP_IPX: /* IPX protocol */
case PPP_VJC_COMP: /* VJ compressed TCP */
case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */
case PPP_MP: /* Multilink protocol */
case PPP_IPV6: /* Internet Protocol Version 6 */
case PPP_COMPFRAG: /* fragment compressed below bundle */
case PPP_COMP: /* compressed packet */
case PPP_MPLS_UC: /* Multi Protocol Label Switching - Unicast */
case PPP_MPLS_MC: /* Multi Protocol Label Switching - Multicast */
case PPP_IPCP: /* IP Control Protocol */
case PPP_ATCP: /* AppleTalk Control Protocol */
case PPP_IPXCP: /* IPX Control Protocol */
case PPP_IPV6CP: /* IPv6 Control Protocol */
case PPP_CCPFRAG: /* CCP at link level (below MP bundle) */
// case PPP_CCP: /* Compression Control Protocol */ (same as PPP_CCPFRAG)
case PPP_MPLSCP: /* MPLS Control Protocol */
case PPP_LCP: /* Link Control Protocol */
case PPP_PAP: /* Password Authentication Protocol */
case PPP_LQR: /* Link Quality Report protocol */
case PPP_CHAP: /* Cryptographic Handshake Auth. Protocol */
case PPP_CBCP: /* Callback Control Protocol */
return 1;
default:
return 0;
}
}
static inline const char *parse_ppp(struct packet *pkt, const char *data, uint16_t len)
{
/*
* https://datatracker.ietf.org/doc/html/rfc1661#section-2
* +----------+-------------+---------+
* | Protocol | Information | Padding |
* | 8/16 bits| * | * |
* +----------+-------------+---------+
*
* https://datatracker.ietf.org/doc/html/rfc1331#section-3.1
* +----------+----------+----------+----------+------------
* | Flag | Address | Control | Protocol | Information
* | 01111110 | 11111111 | 00000011 | 16 bits | *
* +----------+----------+----------+----------+------------
* ---+----------+----------+-----------------
* | FCS | Flag | Inter-frame Fill
* | 16 bits | 01111110 | or next Address
* ---+----------+----------+-----------------
*/
if (unlikely(len < 4))
{
PACKET_LOG_DATA_INSUFFICIENCY(LAYER_TYPE_PPP);
return data;
}
uint16_t hdr_len = 0;
uint16_t next_proto = 0;
// ppp header 1 byte
next_proto = *((uint8_t *)data);
if (next_proto_is_ppp(next_proto))
{
hdr_len = 1;
goto success;
}
// ppp header 2 bytes
next_proto = ntohs(*((uint16_t *)data));
if (next_proto_is_ppp(next_proto))
{
hdr_len = 2;
goto success;
}
// ppp header 4 bytes
next_proto = ntohs(*((uint16_t *)data + 1));
hdr_len = 4;
success:
struct packet_layer *layer = get_free_layer(pkt);
if (unlikely(layer == NULL))
{
return data;
}
uint16_t next_proto = ntohs(*((uint16_t *)data + 1));
SET_LAYER(pkt, layer, LAYER_TYPE_PPP, 4, data, len, 0);
SET_LAYER(pkt, layer, LAYER_TYPE_PPP, hdr_len, data, len, 0);
switch (next_proto)
{
// TESTED
@@ -869,10 +942,8 @@ static inline const char *parse_vlan(struct packet *pkt, const char *data, uint1
static inline const char *parse_pppoe_ses(struct packet *pkt, const char *data, uint16_t len)
{
#define PPPOE_TYPE_IPV4 0x2100
#define PPPOE_TYPE_IPV6 0x5700
if (unlikely(len < 8))
if (unlikely(len < 6))
{
PACKET_LOG_DATA_INSUFFICIENCY(LAYER_TYPE_PPPOE);
return data;
@@ -883,20 +954,10 @@ static inline const char *parse_pppoe_ses(struct packet *pkt, const char *data,
{
return data;
}
uint16_t next_proto = *((uint16_t *)data + 3);
SET_LAYER(pkt, layer, LAYER_TYPE_PPPOE, 8, data, len, 0);
SET_LAYER(pkt, layer, LAYER_TYPE_PPPOE, 6, data, len, 0);
switch (next_proto)
{
// TESTED
case PPPOE_TYPE_IPV4:
return parse_ipv4(pkt, layer->pld_ptr, layer->pld_len);
case PPPOE_TYPE_IPV6:
return parse_ipv6(pkt, layer->pld_ptr, layer->pld_len);
default:
PACKET_LOG_UNSUPPORT_PROTO("pppoe", next_proto);
return layer->pld_ptr;
}
return parse_ppp(pkt, layer->pld_ptr, layer->pld_len);
}
static inline const char *parse_mpls(struct packet *pkt, const char *data, uint16_t len)