ANNOUNCEMENT: Live Wireshark University & Allegro Packets online APAC Wireshark Training Session
July 17th, 2024 | 10:00am-11:55am SGT (UTC+8) | Online

Ethereal-dev: Re: [ethereal-dev] grabbing ppp packets

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Guy Harris <gharris@xxxxxxxxxxxx>
Date: Sun, 19 Dec 1999 20:42:48 -0800
> > > > I would like to grab the ppp-setup, but when I grab from ppp0, I get packets
> > > > as raw-IP. Does anyone know how I can grab all ppp LCP, and NCP packets?
> > > 
> > > On what operating system?
> > 
> > Linux 2.2.13
> > 
> > Problem is that what I get from the ppp-device is only the raw IP-data, not
> > the ppp-encapsulation.
> 
> I'd have to go dive into the kernel code to see why it's doing that,

Hmm.

It looks as if SOCK_PACKET sockets, at least in 2.2.13, *always* try to
push the link-layer header back onto the socket buffer (the driver
advances the data pointer in the socket buffer to remove the link-layer
header before handing the packet upstream, as most network layer code
above it doesn't care about the link-layer header and really doesn't
want to *have* to care about it; SOCK_PACKET, however, exists, at least
in part, to give raw network traffic to userland programs, where "raw"
means "every single octet, including link-layer headers", so it wants to
move the pointer back).

However, it also looks as if the PPP driver might attempt to make it
impossible to do so; "ppp_rcv_rx()" in "drivers/net/ppp.c" does:

        skb_pull(skb, PPP_HDRLEN);      /* pull off ppp header */
        skb->mac.raw   = skb->data;
        ppp->last_recv = jiffies;
        netif_rx (skb);

The

        skb_pull(skb, PPP_HDRLEN);      /* pull off ppp header */

advances "skb->data" by PPP_HDRLEN, so it points to the first octet
*past* the PPP header; "packet_rcv_spkt()", which is the routine that
receives all packets for SOCK_PACKET sockets, does

	skb_push(skb, skb->data-skb->mac.raw);

which backs "skb->data" off by "skb->data-skb->mac.raw" - but the PPP
driver has "helpfully" advanced "skb->mac.raw" to be equal to
"skb->data", so it doesn't bring the PPP header back from the dead.

As for why, over and above all that, you don't see the LCP and NCP
packets:

It appears that those packets, when transmitted by the Linux box, are
transmitted by the PPP daemon writing directly to the serial port; the
serial port has a PPP line discipline, which means that writes cause a
PPP frame to be transmitted.

When that's done, the frame doesn't get handed to "dev_queue_xmit()" or
even to "dev_queue_xmit_nit()", so the transmitted LCP and NCP frames
don't get handed to "network taps" such as the SOCK_PACKET socket that
"libpcap" opens.

*Received* PPP frames have their protocol type looked up in the
"proto_list[]" table in "ppp.c"; that table causes IPv4, IPv6, IPX,
Appletalk, and compressed frames to be handed to various routines which
largely hand them upstream, but all other packets - including LCP and
NCP - are treated as "unclassified" protocols and handed to
"rcv_proto_unknown()", which just queues them up for "pppd" to read and
does *not* appear to queue them up for the network taps.

Given that what it *does* hand to network taps has the PPP header
stripped off, I'm not sure that handing LCP or NCP frames would work
very well in any case....

I.e., the answer appears to be that the Linux PPP implementation, at
least as of the 2.2.13 kernel, simply isn't very friendly towards packet
sniffers.  Maybe "pppd" does something to make those packets available -
i.e., some help arrives from outside the kernl - but I suspect not.