NG_PPTPGRE(4)

πŸ’– NG_PPTPGRE πŸ’–

okay bestie, sit DOWN, because we're talking about ng_pptpgre β€” that's the PPTP GRE protocol netgraph node type from the Kernel Interfaces Manual. yes it's a mouthful, no you're not gonna pronounce it right the first time, and yes it is lowkey iconic. let's get into it πŸ’…


✨ SYNOPSIS ✨

like all the cool netgraph kids, you gotta include the headers first:

#include <sys/types.h>
#include <netgraph/ng_pptpgre.h>

πŸ¦‹ DESCRIPTION πŸ¦‹

so. this node type does Generic Routing Encapsulation (GRE) over IP for the PPTP protocol, exactly as specified by RFC 2637. and when I say "does" I mean it handles the whole glow-up: packet encapsulation, sequencing, acknowledgement, AND an adaptive timeout sliding window mechanism. she's doing a lot, honestly.

🫢 heads up though: this node does NOT touch any of the TCP control protocol or call negotiation that PPTP defines. that's somebody else's job, not hers.

the vibe on the hooks is very specific and you need to get it right:

  • she expects to receive complete IP packets, including the IP header, on the lower hook.
  • but she transmits outgoing frames without any IP header. asymmetry queen πŸ‘‘

the typical setup β€” and this is the classic combo, iykyk β€” is to connect the upper hook to one of the link hooks of an ng_ppp(4) node, and the lower hook to the inet/raw/gre hook of an ng_ksocket(4) node. match made in heaven fr fr ✨


πŸŽ€ HOOKS πŸŽ€

this node type supports the following hooks, and there are literally three of them, so no excuses:

  • session_hhhh β€” Session 0xhhhh data packets headed up to the upper protocol layers 🌸
  • upper β€” same as session_hhhh, but for a single session with a configurable cid (the legacy route, respect your elders)
  • lower β€” the connection down to the lower protocol layers 🫢

πŸ’… CONTROL MESSAGES πŸ’…

she supports all the generic control messages (obviously, she's not a monster), plus these ones:

  • NGM_PPTPGRE_SET_CONFIG (also known as setconfig) β€” this command resets and configures the hook for a session. here's the little detail that trips people up: if the corresponding session_hhhh hook is not connected, then the upper hook gets configured instead. sneaky but fair. this command takes a struct ng_pptpgre_conf as its argument:
/* Configuration for a session */
struct ng_pptpgre_conf {
    u_char      enabled;          /* enables traffic flow */
    u_char      enableDelayedAck; /* enables delayed acks */
    u_char      enableAlwaysAck;  /* always include ack with data */
    u_char      enableWindowing;  /* enable windowing algorithm */
    uint16_t    cid;              /* my call id */
    uint16_t    peerCid;          /* peer call id */
    uint16_t    recvWin;          /* peer recv window size */
    uint16_t    peerPpd;          /* peer packet processing delay
                                     (in 1/10 of a second) */
};

okay let's break down the fields because they all matter:

  • enabled β€” turns traffic flow through the node on. the on/off switch, the vibe gate.
  • enableDelayedAck β€” enables delayed acknowledgement, max 250 milliseconds. this is a genuinely useful optimization and you should generally have it turned ON. bestie, leave it on.
  • enableAlwaysAck β€” sends acknowledgements with every data packet. probably helpful as well, so like, sure πŸ’
  • enableWindowing β€” enables the PPTP packet windowing mechanism as specified by the protocol. and here's the tea: disabling it makes the node violate the protocol, which can confuse other PPTP peers… but it often results in better performance. the windowing mechanism is, and I quote, a design error in the PPTP protocol β€” L2TP, PPTP's successor, straight up removes it. not me defending a protocol's mistakes but ok πŸ’€
  • the remaining fields are as supplied by the PPTP virtual call setup process. you don't make those up, you get them handed to you.
  • NGM_PPTPGRE_GET_CONFIG (aka getconfig) β€” takes a two byte argument as cid and returns the current configuration as a struct ng_pptpgre_conf. give her a cid, she gives you the config. transactional icon πŸ’–
  • NGM_PPTPGRE_GET_STATS (aka getstats) β€” returns a struct ng_pptpgre_stats stuffed with various node statistics. numbers! love that for us πŸ“Š
  • NGM_PPTPGRE_CLR_STATS (aka clrstats) β€” resets the node statistics. clean slate energy ✨
  • NGM_PPTPGRE_GETCLR_STATS (aka getclrstats) β€” atomically gets AND resets the node statistics, returning a struct ng_pptpgre_stats. one message, two jobs, main character behavior πŸ‘‘

🌈 SHUTDOWN 🌈

this node shuts down when she receives a NGM_SHUTDOWN control message β€” or when both hooks have been disconnected. she's not sticking around if nobody's talking to her. bye bestie πŸ‘‹


⭐ SYSCTL VARIABLES ⭐

there's a whole set of sysctl(8) variables that control how well this node deals with a certain amount of packet reorder that sometimes happens in transit. and why does that matter? because packet reorder results in packet drops β€” unless the order gets restored β€” since the PPP protocol cannot deliver reordered data. periodt.

here they are, with their default values and what they mean:

  • net.graph.pptpgre.reorder_max: 1 β€” defines the maximum length of the node's private reorder queue, which is what she uses to keep data waiting for late packets. a value of zero disables reordering entirely. the default value lets the node restore the order for two packets swapped in transit. bigger values let the node deliver packets that are late after more packets in sequence β€” but at the cost of increased kernel memory usage. so like, more patience, more RAM, your call πŸ’­
  • net.graph.pptpgre.reorder_timeout: 1 β€” defines the time value, in miliseconds, used to wait for late packets. she'll wait. but only for that long. ⏳

πŸ‘‘ SEE ALSO πŸ‘‘

and the reading list, because we stay educated πŸ“š:

  • K. Hamzeh, G. Pall, W. Verthein, J. Taarud, W. Little, and G. Zorn, Point-to-Point Tunneling Protocol (PPTP), RFC 2637.
  • S. Hanks, T. Li, D. Farinacci, and P. Traina, Generic Routing Encapsulation over IPv4 networks, RFC 1702.

🌸 HISTORY 🌸

the ng_pptpgre node type was implemented in FreeBSD 4.0. vintage, honestly. she's been serving since before some of us could read 🫢


πŸ’œ AUTHORS πŸ’œ

Archie Cobbs <archie@FreeBSD.org> β€” thank you for your service, king πŸ‘‘


πŸ’€ BUGS πŸ’€

okay so, the one thing to know: the node should not expect incoming GRE packets to have an IP header. this behavior is inherited from the (converse) behavior of raw IP sockets β€” it's a whole thing, it's legacy, don't @ her. the fix, per the docs, is to use an intermediate node that strips IP headers in one direction instead. that's the move. do that. πŸ™ˆ


and that's the whole page, bestie!! πŸŽ€βœ¨πŸ¦‹

this was served up as part of the Debian build of the manual, dated November 4, 2018. go forth and encapsulate responsibly πŸ’–

πŸ“¦ where this page comes from