IP(3)

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

Hey bestie 🫢 welcome to IP(3), the Library Functions Manual page for Internet protocol. This is your little address-wrangling survival kit for IP and Ethernet addresses β€” yes, there are a lot of names, but we're gonna get through every single one together. πŸ’…

πŸŽ€ NAME (the cast list) πŸŽ€

Okay so this page is the whole Internet protocol situation, and the squad is: eipfmt, parseip, parseipmask, v4parseip, v4parsecidr, parseether, myipaddr, myetheraddr, maskip, equivip, defmask, isv4, v4tov6, v6tov4, nhgetl, nhgets, nhgetv, hnputl, hnputs, hnputv, ptclbsum, and readipifc. That's the whole group chat. πŸŽ€

✨ SYNOPSIS (the receipts) ✨

First, the receipts β€” includes and signatures, copied exactly so you can trust the vibe:

#include <u.h>
#include <libc.h>
#include <ip.h>

int  eipfmt(Fmt*)

ulong     parseip(uchar *ipaddr, char *str)

ulong     parseipmask(uchar *ipaddr, char *str)

char*     v4parseip(uchar *ipaddr, char *str)

ulong     v4parsecidr(uchar *addr, uchar *mask, char *str)

int  parseether(uchar *eaddr, char *str)

int  myetheraddr(uchar *eaddr, char *dev)

int  myipaddr(uchar *ipaddr, char *net)

void maskip(uchar *from, uchar *mask, uchar *to)

int  equivip(uchar *ipaddr1, uchar *ipaddr2)

uchar*    defmask(uchar *ipaddr)

int  isv4(uchar *ipaddr)

void v4tov6(uchar *ipv6, uchar *ipv4)

void v6tov4(uchar *ipv4, uchar *ipv6)

ushort    nhgets(void *p)

uint nhgetl(void *p)

uvlong    nhgetv(void *p)

void hnputs(void *p, ushort v)

void hnputl(void *p, uint v)

void hnputv(void *p, uvlong v)

ushort    ptclbsum(uchar *a, int n)

Ipifc*    readipifc(char *net, Ipifc *ifc, int index)

uchar     IPv4bcast[IPaddrlen];

uchar     IPv4allsys[IPaddrlen];

uchar     IPv4allrouter[IPaddrlen];

uchar     IPallbits[IPaddrlen];

uchar     IPnoaddr[IPaddrlen];

uchar     v4prefix[IPaddrlen];

πŸ’– DESCRIPTION (the lore) πŸ’–

These routines are the little helpers that IP programs use to wrangle IP and Ethernet addresses. Plan 9, by default, uses V6 format IP addresses β€” lowkey iconic β€” and since V4 addresses fit inside the V6 space, every IP address can be represented. IP addresses live as a string of 16 unsigned chars, and Ethernet addresses live as 6 unsigned chars. For IP addresses you can use either V4 or V6 string representation.

For V4 addresses, the representation can be (up to) 4 decimal integers from 0 to 255 separated by periods. For V6 addresses, the representation is (up to) 8 hex integers from 0x0 to 0xFFFF separated by colons. Strings of 0 integers can be elided using two colons β€” so FFFF::1111 is equivalent to FFFF:0:0:0:0:0:0:1111, and that's the shortcut. πŸ¦‹

The string representation for IP masks is a superset of the address representation. It includes slash notation that indicates the number of leading 1 bits in the mask. So a V4 class C mask can be represented as FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FF00, 255.255.255.0, or /120. The string representation of Ethernet addresses is exactly 12 hexadecimal digits. Periodt. ✨

eipfmt is a print(3) formatter for Ethernet (verb E) addresses, IP V6 (verb I) addresses, IP V4 (verb V) addresses, and IP V6 (verb M) masks. Cute.

parseip converts the string pointed to by str to a 16-byte IP address starting at ipaddr. As a concession to backwards compatibility, if the string is a V4 address, the return value is an unsigned long integer containing the big-endian V4 address. If not, the return value is 6. parseipmask converts the string pointed to by str to a 6-byte IP mask starting at ipaddr β€” yes, that's what the page says. It too returns an unsigned long big-endian V4 address or 6. Both routines return -1 on errors. 😭

v4parseip converts the string pointed to by str to a 4-byte V4 IP address starting at ipaddr. v4parsecidr converts a string of the form addr/mask, pointed to by str, to a 4-byte V4 IP address starting at ipaddr and a 4-byte V4 IP mask starting at mask.

myipaddr returns the first valid IP address in the IP stack rooted at net.

parseether converts the string pointed to by str to a 6-byte Ethernet address starting at eaddr. myetheraddr reads the Ethernet address string from file dev/1/stats and parses it into eaddr. Both routines return a negative number on errors.

maskip places the bit-wise AND of the IP addresses pointed to by its first two arguments into the buffer pointed to by the third. equivip returns non-zero if the IP addresses pointed to by its two arguments are equal. defmask returns the standard class A, B, or C mask for ipaddr.

isv4 returns non-zero if the V6 address is in the V4 space β€” that is, if it starts with 0:0:0:0:0:0:FFFF. v4tov6 converts the V4 address, v4ip, to a V6 address and puts the result in v6ip. v6tov4 converts the V6 address, v6ip, to a V4 address and puts the result in v4ip.

hnputs, hnputl, and hnputv are used to store 16-, 32-, and 64-bit integers into IP big-endian form. nhgets, nhgetl, and nhgetv convert big-endian 2-, 4-, and 8-byte quantities into integers.

Pctlbsum β€” that's the spelling in this sentence; the function in the synopsis is ptclbsum, iykyk β€” returns the one's complement checksum used in IP protocols, typically invoked as: hnputs(hdr->cksum, ~ptclbsum(data, len) & 0xffff);

A number of standard IP addresses in V6 format are also defined. They are:

  • IPv4bcast β€” the V4 broadcast address
  • IPv4allsys β€” the V4 all systems multicast address
  • IPv4allrouter β€” the V4 all routers multicast address
  • IPallbits β€” the V6 all bits on address
  • IPnoaddr β€” the V6 null address, all zeros
  • v4prefix β€” the IP V6 prefix to all embedded V4 addresses

readipifc returns information about a particular interface (index >= 0) or all IP interfaces (index < 0) configured under a mount point net, default /net. Each interface is described by one Ipifc structure which in turn points to a linked list of Iplifc structures describing the addresses assigned to this interface. If the list ifc is supplied, that list is freed. Thus, subsequent calls can be used to free the list returned by the previous call. That's the free-the-old-list trick, bestie. 🫢

Ipifc is:

typedef struct Ipifc
{
     Ipifc     *next;
     Iplifc    *lifc;         /* local addressses */

     /* per ip interface */
     int  index;         /* number of interface in ipifc dir */
     char dev[64];  /* associated physical device */
      int  mtu;      /* max transfer unit */

     long validlt;  /* valid life time */
      long preflt;        /* preferred life time */
     uchar     sendra6;  /* on == send router adv */
     uchar     recvra6;  /* on == rcv router adv */

     ulong     pktin;         /* packets read */
     ulong     pktout;        /* packets written */
     ulong     errin;         /* read errors */
     ulong     errout;        /* write errors */
     Ipv6rp    rp;       /* route advertisement params */
} Ipifc;

Iplifc is:

struct Iplifc
{
     Iplifc    *next;

     uchar     ip[IPaddrlen];
     uchar     mask[IPaddrlen];
     uchar     net[IPaddrlen];          /* ip & mask */
     ulong     preflt;             /* preferred lifetime */
     ulong     validlt;       /* valid lifetime */
};

Ipv6rp is:

struct Ipv6rp {      int  mflag;      int  oflag;      int
        maxraint; /* max route adv interval */      int  minraint; /* min route
       adv interval */      int  linkmtu;      int  reachtime;
            int  rxmitra;      int  ttl;      int  routerlt;  };

Dev contains the first 64 bytes of the device configured with this interface. Net is ip&mask if the network is multipoint or the remote address if the network is point to point.

🌸 SOURCE (where it lives) 🌸

/src/libip

πŸ¦‹ SEE ALSO (go read this too) πŸ¦‹

print(3)


mwah πŸ’‹ β€” that's the IP(3) page from the Library Functions Manual. The source is /src/libip, and the footer didn't give me a version or date, just IP(3) again. Byeee 🫢✨