NDB(3)

πŸ“¦ version 0_git20260208, in alpine 3.24, arch rolling, nixos 26.05, nixpkgs unstable

✨ NDB(3) ✨

okay so bestie, gather round, because this is the network database library and it's literally the backbone of network admin programs searching the network database πŸ’…. These routines operate on the database files described in ndb(7), and they're giving main character energy for sure.


🌸 SYNOPSIS 🌸

#include <u.h>
#include <libc.h>
#include <bio.h>
#include <ndb.h>

Ndb*       ndbopen(char *file)

Ndb*       ndbcat(Ndb *db1, Ndb *db2)

Ndb*       ndbchanged(Ndb *db)

int        ndbreopen(Ndb *db)

void       ndbclose(Ndb *db)

Ndbtuple*  ndbsearch(Ndb *db, Ndbs *s, char *attr, char *val)

Ndbtuple*  ndbsnext(Ndbs *s, char *attr, char *val)

char*      ndbgetvalue(Ndb *db, Ndbs *s, char *attr, char *val,
           char *rattr, Ndbtuple **tp)

char*      ipattr(char *name)

Ndbtuple*  ndbgetipaddr(Ndb *db, char *sys);

Ndbtuple*  ndbipinfo(Ndb *db, char *attr, char *val, char **attrs,
           int nattr)

ulong      ndbhash(char *val, int hlen)

Ndbtuple*  ndbparse(Ndb *db)

Ndbtuple*  ndbfindattr(Ndbtuple *entry, Ndbtuple *line, char *attr)

void       ndbfree(Ndbtuple *db)

Ndbtuple*  ndbdiscard(Ndbtuple  *t, Ndbtuple *a)

Ndbtuple*  ndbconcatenate(Ndbtuple *a, Ndbtuple *b);

Ndbtuple*  ndbreorder(Ndbtuple *t, Ndbtuple *a);

Ndbtuple*  ndbsubstitute(Ndbtuple *t, Ndbtuple *from, Ndbtuple *to);

πŸ’– DESCRIPTION πŸ’–

So these routines? They're what network administrative programs use to search the network database, no cap. They work on the database files described in ndb(7) β€” go read that one too, bestie.

Ndbopen opens the database file and calls malloc(3) to allocate a buffer for it. If file is zero, then literally all network database files get opened. Slay.

Ndbcat concatenates two open databases together. Either argument can be nil, it's chill like that.

Ndbreopen checks if the database files associated with db have changed, and if they have, it throws out any cached information and reopens the files. Fresh start energy ✨.

Ndbclose closes any database files associated with db and frees all the storage associated with them. Clean up, clean up 🧹.

Ndbsearch and ndbsnext search a database for an entry containing the attribute/value pair, attr=val. Ndbsearch finds the first match, and ndbsnext finds each successive match. On a successful search, both return a linked list of Ndbtuple structures acquired by malloc(3) that represent the attribute/value pairs in the entry. On failure? They return zero. 😭

typedef struct Ndbtuple Ndbtuple;
struct Ndbtuple {
        char      attr[Ndbalen];
        char      *val;
        Ndbtuple  *entry;
        Ndbtuple  *line;
        ulong     ptr;    /* for the application; starts 0 */
        char      valbuf[Ndbvlen];  /* initial allocation for val */
};

The entry pointers chain together all pairs in the entry in a null-terminated list. The line pointers chain together all pairs on the same line in a circular list. So a program can implement 2 levels of binding for pairs in an entry. In general, pairs on the same line are bound tighter than pairs on different lines. iykyk 🫢

The s argument of ndbsearch has type Ndbs and should be pointed to valid storage before you call ndbsearch β€” it'll fill it with information that ndbsnext uses to link successive searches. The structure Ndbs looks like:

typedef struct Ndbs Ndbs;
struct Ndbs {
        Ndb      *db;   /* data base file being searched */
        ...
        Ndbtuple *t;    /* last attribute value pair found */
};

The t field points to the pair within the entry matched by the ndbsearch or ndbsnext. Obsessed with this level of organization tbh.

Ndbgetvalue searches the database for an entry containing not only an attribute/value pair, attr=val, but also a pair with the attribute rattr. If it's successful, it returns a malloced copy of the null-terminated value associated with rattr. If tp is non-nil, then *tp will point to the entry. Otherwise, the entry will be freed.

Ndbfree frees a list of tuples returned by one of the other routines. Bye bye πŸ‘‹.

Ipattr takes the name of an IP system and returns the attribute it corresponds to:

  • dom β€” domain name
  • ip β€” Internet number
  • sys β€” system name

Ndbgetipaddr looks in db for an entry matching sys as the value of a sys= or dom= attribute/value pair, and returns all IP addresses in the entry. If sys is already an IP address, a tuple containing just that address is returned. Easy peasy πŸ“.

Ndbipinfo looks up Internet protocol information about a system. This is an IP-aware search, okay? It looks first for information in the system's database entry, and then in the database entries for any IP subnets or networks containing the system. The system is identified by the attribute/value pair, attr=val. Ndbipinfo returns a list of tuples whose attributes match the attributes in the n element array attrs. For example, consider these database entries describing a network, a subnetwork, and a system:

ipnet=big ip=10.0.0.0
           dns=dns.big.com
           smtp=smtp.big.com
ipnet=dept ip=10.1.1.0 ipmask=255.255.255.0
           smtp=smtp1.big.com
ip=10.1.1.4 dom=x.big.com
           bootf=/386/9pc

Calling

ndbipinfo(db, "dom", "x.big.com", ["bootf" "smtp" "dns"], 3)

will return the tuples bootf=/386/9pc, smtp=smtp1.big.com, and dns=dns.big.com. Iconic behavior honestly πŸ”₯.


The next three routines are used by programs that create the hash tables and database files. Ndbhash computes a hash offset into a table of length hlen for the string val. Ndbparse reads and parses the next entry from the database file. Multiple calls to ndbparse parse sequential entries in the database file. A zero is returned at end of file.

Ndbfindattr searches entry for the tuple with attribute attr and returns a pointer to the tuple. If line points to a particular line in the entry, the search starts there and then wraps around to the beginning of the entry. Sneaky but efficient, we love to see it πŸ’œ.


All of the routines provided to search the database give you an always consistent view of the relevant files. Fr fr. However, it may be advantageous for an application to read in the whole database using ndbopen and ndbparse and provide its own search routines. The ndbchanged routine can be used by the application to periodically check for changes. It returns zero if none of the files comprising the database have changed, and non-zero if they have. Periodic vibe check, literally πŸ¦‹.


Finally, a number of routines are provided for manipulating tuples. Let's gooo πŸŽ€:

Ndbdiscard removes attr/val pair a from tuple t and frees it. If a isn't in t, it's just freed. Ghosted and freed, both.

Ndbconcatenate concatenates two tuples and returns the result. Either or both tuples may be nil.

Ndbreorder reorders a tuple t to make the line containing attr/val pair a first in the entry, and makes a first in its line. Reordering? We're rearranging the group chat πŸ’….

Ndbsubstitute replaces a single att/val pair from in t with the tuple to. All attr/val pairs in to end up on the same line. from is freed. Swapped and slayed ✨.


πŸŽ€ FILES πŸŽ€

  • /ndb β€” directory of network database files

⭐ SOURCE ⭐

  • /src/libndb

🌈 SEE ALSO 🌈

ndb(1) ndb(7)


πŸ’€ DIAGNOSTICS πŸ’€

Ndbgetvalue and ndblookvalue set errstr to buffer too short if the buffer provided isn't long enough for the returned value. So like, make sure your buffer is big enough, bestie, or it's giving error 😭.


πŸ™ˆ BUGS πŸ™ˆ

Ndbgetval and ndblookval are deprecated versions of ndbgetvalue and ndblookvalue. No cap, they're old news. They expect a fixed 64 byte long result buffer and existed back when the values of a Ndbtuple structure were fixed length. Ancient history, we don't stan 🧚.


mwah πŸ’‹ that's the whole page β€” brought to you by the Library Functions Manual, NDB(3), dated and versioned just the way the original footer says it. now go search some databases, you gorgeous genius, and remember: tuples are just vibes with pointers 🫢✨