MDCHAIN(9)

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

πŸ’… MDCHAIN(9) β€” the mbuf dissecting girlies ✨

okay so bestie, this is mdchain(9), from the Kernel Developer's Manual, and it's literally the whole toolkit for taking an mbuf chain apart and turning it into actual data types. no cap, it's giving "surgery but make it packets." πŸ¦‹

The functions we're talking about are: mdchain, md_initm, md_done, md_append_record, md_next_record, md_get_uint8, md_get_uint16, md_get_uint16be, md_get_uint16le, md_get_uint32, md_get_uint32be, md_get_uint32le, md_get_int64, md_get_int64be, md_get_int64le, md_get_mem, md_get_mbuf, and md_get_uio β€” a whole friend group, honestly. πŸ’–


✨ SYNOPSIS ✨

first things first, you gotta opt in:

options LIBMCHAIN
kldload libmchain

then the includes, in this exact order:

#include <sys/param.h>
#include <sys/uio.h>
#include <sys/mchain.h>

and here's the full cast, one by one πŸ‘‘:

void
md_initm(struct mdchain *mdp, struct mbuf *m);

void
md_done(struct mdchain *mdp);

void
md_append_record(struct mdchain *mdp, struct mbuf *top);

int
md_next_record(struct mdchain *mdp);

int
md_get_uint8(struct mdchain *mdp, uint8_t *x);

int
md_get_uint16(struct mdchain *mdp, uint16_t *x);

int
md_get_uint16be(struct mdchain *mdp, uint16_t *x);

int
md_get_uint16le(struct mdchain *mdp, uint16_t *x);

int
md_get_uint32(struct mdchain *mdp, uint32_t *x);

int
md_get_uint32be(struct mdchain *mdp, uint32_t *x);

int
md_get_uint32le(struct mdchain *mdp, uint32_t *x);

int
md_get_int64(struct mdchain *mdp, int64_t *x);

int
md_get_int64be(struct mdchain *mdp, int64_t *x);

int
md_get_int64le(struct mdchain *mdp, int64_t *x);

int
md_get_mem(struct mdchain *mdp, caddr_t target, int size, int type);

int
md_get_mbuf(struct mdchain *mdp, int size, struct mbuf **m);

int
md_get_uio(struct mdchain *mdp, struct uio *uiop, int size);

🌸 DESCRIPTION 🌸

so these functions decompose mbuf chains into various data types. the mdchain structure is your working context β€” your little main character notebook β€” and you should initialize it through a call of the mb_initm() function. it has these fields:

  • md_top (struct mbuf *) β€” a pointer to the top of the parsed mbuf chain.
  • md_cur (struct mbuf *) β€” a pointer to the currently parsed mbuf.
  • md_pas (int) β€” offset in the current mbuf.

md_done() disposes of the mbuf chain pointed to by the mdp->md_top field and sets that field to NULL. cleanup queen πŸ’…

md_append_record() appends a new mbuf chain using the m_nextpkt field to form a single linked list of mbuf chains. and if mdp->md_top is NULL, it behaves exactly as md_initm() does. iykyk.

md_next_record() extracts the next mbuf chain and disposes the current one, if any. for a new mbuf chain it calls md_initm(). if there's no data left, it returns ENOENT. 😭

all the md_get_*() functions perform an actual copy of the data from an mbuf chain. the ones with le or be suffixes will convert to little- or big-endian data formats. slay.

md_get_mem() copies size bytes of data specified by the source argument from an mbuf chain. the type argument tells it which method to use for the copy, and it can be one of these:

  • MB_MSYSTEM β€” use the bcopy() function.
  • MB_MUSER β€” use the copyin(9) function.
  • MB_MINLINE β€” use an "inline" loop which doesn't call any function at all. no middleman, we love to see it.

if target is NULL, no actual copy happens β€” the function just skips the given number of bytes. iconic skip behavior honestly.


πŸ”₯ RETURN VALUES πŸ”₯

all the int functions return zero if successful, otherwise an error code comes back at you.

⚠️ bestie please read this one: after a failure of any function, the mbuf chain is left in the broken state, and only md_done() can safely be called to destroy it. do not try anything else. do not pass go. πŸ’€

πŸŽ€ EXAMPLES πŸŽ€

here's the vibe, literally verbatim:

struct mdchain *mdp;
struct mbuf *m;
uint16_t length;
uint8_t byte;

receive(so, &m);
md_initm(mdp, m);
if (md_get_uint8(mdp, &byte) != 0 ||
    md_get_uint16le(mdp, &length) != 0)
        error = EBADRPC;
mb_done(mdp);

πŸ’œ SEE ALSO πŸ’œ


πŸ‘‘ AUTHORS πŸ‘‘

this manual page was written by Boris Popov <bp@FreeBSD.org>. thank you boris, king behavior. 🫢


okay that's the whole page bestie, you're so ready now. πŸ’–βœ¨

this one came from Debian, dated February 28, 2001 β€” yeah she's an elder icon but she still ate, periodt. πŸ“πŸŒˆ

πŸ“¦ where this page comes from