NETGRAPH(3)

πŸ“¦ version 15.1, in freebsd 14.5, freebsd 15.1

πŸ¦‹ netgraph(3) πŸ¦‹ β€” the netgraph user library, bestie edition

okay so first things first: this is the manual page for NETGRAPH(3), which lives in the Netgraph User Library (libnetgraph, -lnetgraph). πŸ’– It's the user-mode side of the kernel's netgraph thing, and honestly? It's giving "networking but make it modular." Let's get into it. ✨


🌸 SYNOPSIS 🌸

Like, here's the whole squad, exactly as declared:

#include <netgraph.h>

int
NgMkSockNode(const char *name, int *csp, int *dsp);

int
NgNameNode(int cs, const char *path, const char *fmt, ...);

int
NgSendMsg(int cs, const char *path, int cookie, int cmd,
    const void *arg, size_t arglen);

int
NgSendAsciiMsg(int cs, const char *path, const char *fmt, ...);

int
NgSendReplyMsg(int cs, const char *path, struct ng_mesg *msg,
    const void *arg, size_t arglen);

int
NgRecvMsg(int cs, struct ng_mesg *rep, size_t replen, char *path);

int
NgAllocRecvMsg(int cs, struct ng_mesg **rep, char *path);

int
NgRecvAsciiMsg(int cs, struct ng_mesg *rep, size_t replen, char *path);

int
NgAllocRecvAsciiMsg(int cs, struct ng_mesg **rep, char *path);

int
NgSendData(int ds, const char *hook, const u_char *buf, size_t len);

int
NgRecvData(int ds, u_char *buf, size_t len, char *hook);

int
NgAllocRecvData(int ds, u_char **buf, char *hook);

int
NgSetDebug(int level);

void
NgSetErrLog(void (*log)(const char *fmt, ...),
    void (*logx)(const char *fmt, ...));

✨ DESCRIPTION ✨

So these functions let your user-mode program ~participate~ in the kernel netgraph(4) graph-based networking system, by using the netgraph socket node type (peep ng_socket(4)). Basically you get to be part of the graph. main character energy, honestly. πŸ‘‘

πŸŽ€ NgMkSockNode()

Call this one first, okay? It creates a new socket type netgraph node with associated control and data sockets. If name is non-NULL, the node gets that global name assigned to it. The csp and dsp arguments get set to the newly opened control and data sockets for the node β€” and either csp or dsp can be NULL if you only want one of them. πŸ’… Also, NgMkSockNode() loads the socket node type KLD if it's not already loaded. Considerate king behavior.

πŸŽ€ NgNameNode()

Assigns a global name to the node addressed by path. That's it, that's the function. Slay.

πŸŽ€ NgSendMsg()

Sends a binary control message from the socket node associated with control socket cs to the node addressed by path. The cookie tells you how to interpret cmd, which indicates a specific command. Extra argument data (if there is any) goes in arg and arglen. The cookie, cmd, and argument data are all defined by the header file corresponding to the type of node you're addressing.

It returns the unique, non-negative token value chosen for the message header. That value is typically used to associate replies. πŸ”₯

πŸŽ€ NgSendReplyMsg()

Use this to send a reply to a previously received control message. The original message header should be pointed to by msg.

πŸŽ€ NgSendAsciiMsg()

Does the same thing as NgSendMsg(), but with a glow-up: it adds support for ASCII encoding of control messages. It formats its input a la printf(3), then sends the resulting ASCII string to the node in a NGM_ASCII2BINARY control message. The node sends back a binary version of the message, which then gets sent back to the node just like with NgSendMsg(). Same deal as NgSendMsg(): the message token value is returned. 🫢

Heads up bestie β€” ASCII conversion may not be supported by all node types. πŸ™ˆ

πŸŽ€ NgRecvMsg()

Reads the next control message received by the node associated with control socket cs. The message and any extra argument data must fit in replen bytes. If path is non-NULL, it must point to a buffer of at least NG_PATHSIZ bytes, which gets filled in (and NUL terminated) with the path to the node the message came from.

The length of the control message is returned. A return value of zero means the socket was closed. 😭

πŸŽ€ NgAllocRecvMsg()

Works exactly like NgRecvMsg(), except the buffer for a message is dynamically allocated so a message never gets truncated. The size of the buffer equals the socket's receive buffer size. You, the caller, are responsible for freeing the buffer when you don't need it anymore. πŸ’œ

πŸŽ€ NgRecvAsciiMsg()

Works exactly like NgRecvMsg(), except that after the message is received, any binary arguments get converted to ASCII by sending a NGM_BINARY2ASCII request back to the originating node. The result is the same as NgRecvMsg(), except the reply arguments field will contain a NUL-terminated ASCII version of the arguments (and the reply header argument length field will be adjusted). ✨

πŸŽ€ NgAllocRecvAsciiMsg()

Works exactly like NgRecvAsciiMsg(), except the buffer for a message is dynamically allocated so nothing gets truncated. Buffer size equals the socket's receive buffer size. Caller frees the buffer. You know the drill by now. πŸŽ€

πŸŽ€ NgSendData()

Writes a data packet out on the specified hook of the node corresponding to data socket ds. The node must already be connected to some other node via that hook β€” no cold-calling strangers, okay?

πŸŽ€ NgRecvData()

Reads the next data packet (of up to len bytes) received by the node corresponding to data socket ds, and stores it in buf, which must be large enough to hold the entire packet. If hook is non-NULL, it must point to a buffer of at least NG_HOOKSIZ bytes, which gets filled in (and NUL terminated) with the name of the hook the data was received on.

The length of the packet is returned. A return value of zero means the socket was closed. πŸ’€

πŸŽ€ NgAllocRecvData()

Works exactly like NgRecvData(), except the buffer for a data packet is dynamically allocated so a data packet never gets truncated. The size of the buffer equals the socket's receive buffer size. Caller frees the buffer. 🫢

πŸŽ€ NgSetDebug() and NgSetErrLog()

These two are the debugging girlies. NgSetDebug() sets the debug level (if non-negative) and returns the old setting. Higher debug levels = more verbosity. The default is 0.

All debug and error messages are logged via the functions specified in the most recent call to NgSetErrLog(). The default logging functions are vwarn(3) and vwarnx(3).

At debug level 3, the library attempts to display control message arguments in ASCII format β€” but that results in additional messages being sent, which may interfere with debugging. 😭 At even higher levels, even those additional messages get displayed, etc. It's turtles all the way down, bestie.

πŸŽ€ lil extra notes ngl

Note that select(2) can be used on the data and the control sockets to detect the presence of incoming data and control messages, respectively. Data and control packets are always written and read atomically, i.e. in one whole piece. No half-sends, no crumbs. ✨

User mode programs must be linked with the -lnetgraph flag to link in this library. Don't forget, or you'll be sad. πŸ₯Ί


πŸ”₯ INITIALIZATION πŸ”₯

To enable netgraph in your kernel, either:

  • your kernel must be compiled with options NETGRAPH in the kernel configuration file, or
  • the netgraph(4) and ng_socket(4) KLD modules must have been loaded via kldload(8).

Pick one. Either slaps. πŸ’…


⭐ RETURN VALUES ⭐

  • NgSetDebug() returns the previous debug setting.
  • NgSetErrLog() has no return value. Nothing. Void. Empty. πŸ«₯
  • All other functions return -1 if there was an error, and set errno accordingly.
  • A return value of zero from NgRecvMsg() or NgRecvData() means the netgraph socket has been closed. 😭

For NgSendAsciiMsg() and NgRecvAsciiMsg(), these additional errors are possible:

  • [ENOSYS] β€” The node type does not know how to encode or decode the control message.
  • [ERANGE] β€” The encoded or decoded arguments were too long for the supplied buffer.
  • [ENOENT] β€” An unknown structure field was seen in an ASCII control message.
  • [EALREADY] β€” The same structure field was specified twice in an ASCII control message. (Not me duplicating fields πŸ’€)
  • [EINVAL] β€” ASCII control message parse error or illegal value.
  • [E2BIG] β€” ASCII control message array or fixed width string buffer overflow.

🌈 SEE ALSO 🌈

select(2), socket(2), warnx(3), kld(4), netgraph(4), ng_socket(4)


🧚 HISTORY 🧚

The netgraph system was designed and first implemented at Whistle Communications, Inc. in a version of FreeBSD 2.2 customized for the Whistle InterJet. Iconic origin story tbh. πŸ‘‘


πŸ‘‘ AUTHORS πŸ‘‘

Archie Cobbs <archie@FreeBSD.org> β€” thank you king 🫢


okay that's the whole page, bestie β€” this gem came out of Debian, dated May 15, 2020. Now go forth and graph some nets. πŸ’…βœ¨πŸŽ€

πŸ“¦ where this page comes from