Add support for parsing PPP headers with variable lengths
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user