blob: da33860337deecd8061a997c84cd5e67005c098f [file] [log] [blame]
/*
* Copyright 2013 Google Inc.
* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.
*/
#ifndef ROS_KERN_PLAN9_H
#define ROS_KERN_PLAN9_H
#include <setjmp.h>
#include <atomic.h>
#include <apipe.h>
#include <rwlock.h>
#include <rendez.h>
#include <kthread.h>
/* The lock issue is still undecided. For now, we preserve the lock type
* and plan to revisit the issue when it makes sense.
*/
/* qlocks are plan9's binary sempahore */
typedef struct semaphore qlock_t;
#define qlock_init(x) sem_init((x), 1)
#define qlock(x) sem_down(x)
#define qunlock(x) sem_up(x)
#define canqlock(x) sem_trydown(x)
/* ilock is a lock that occurs during interrupts. */
#define ilock(x) spin_lock_irqsave(x)
#define iunlock(x) spin_unlock_irqsave(x)
/* command tables for drivers. */
enum
{
NCMDFIELD = 128
};
struct cmdbuf {
char *buf;
char **f;
int nf;
};
struct cmdtab {
int index; /* used by client to switch on result */
char *cmd; /* command name */
int narg; /* expected #args; 0 ==> variadic */
};
/* UTF support is removed.
*/
enum {
UTFmax = 3, /* maximum bytes per rune */
Runesync = 0x80, /* cannot represent part of a UTF sequence */
Runeself = 0x80, /* rune and UTF sequences are the same (<) */
Runeerror = 0xFFFD, /* decoding error in UTF */
};
/* defines for queue state -- currently used in qio.c */
/* queue state bits, Qmsg, Qcoalesce, and Qkick can be set in qopen */
enum {
/* Queue.state */
Qstarve = (1 << 0), /* consumer starved */
Qmsg = (1 << 1), /* message stream */
Qclosed = (1 << 2), /* queue has been closed/hungup */
Qflow = (1 << 3), /* producer flow controlled */
Qcoalesce = (1 << 4), /* coallesce packets on read */
Qkick = (1 << 5), /* always call the kick routine after qwrite */
};
/* stuff which has no equal. */
#define DEVDOTDOT -1
#define NUMSIZE 12 /* size of formatted number */
#define NUMSIZE32 9 /* max size of formatted 32 bit number */
#define NUMSIZE64 20 /* max size of formatted 64 bit number */
#define READSTR 4000 /* temporary buffer size for device reads */
/*
* Syscall data structures
*/
#define MORDER 0x0003 /* mask for bits defining order of mounting */
#define MREPL 0x0000 /* mount replaces object */
#define MBEFORE 0x0001 /* mount goes before others in union directory */
#define MAFTER 0x0002 /* mount goes after others in union directory */
#define MCREATE 0x0004 /* permit creation in mounted directory */
#define MCACHE 0x0010 /* cache some data */
#define MMASK 0x0017 /* all bits on */
#define NCONT 0 /* continue after note */
#define NDFLT 1 /* terminate after note */
#define NSAVE 2 /* clear note but hold state */
#define NRSTR 3 /* restore saved state */
#define ERRMAX 128 /* max length of error string */
#define KNAMELEN 28 /* max length of name held in kernel */
/* bits in Qid.type */
#define QTDIR 0x80 /* type bit for directories */
#define QTAPPEND 0x40 /* type bit for append only files */
#define QTEXCL 0x20 /* type bit for exclusive use files */
#define QTMOUNT 0x10 /* type bit for mounted channel */
#define QTAUTH 0x08 /* type bit for authentication file */
#define QTFILE 0x00 /* plain file */
/* bits in Dir.mode */
#define DMDIR 0x80000000 /* mode bit for directories */
#define DMAPPEND 0x40000000 /* mode bit for append only files */
#define DMEXCL 0x20000000 /* mode bit for exclusive use files */
#define DMMOUNT 0x10000000 /* mode bit for mounted channel */
#define DMREAD 0x4 /* mode bit for read permission */
#define DMWRITE 0x2 /* mode bit for write permission */
#define DMEXEC 0x1 /* mode bit for execute permission */
enum {
DELTAFD = 20 /* incremental increase in Fgrp.fd's */
};
/*
* Access types in namec & channel flags
*/
enum {
Aaccess, /* as in stat, wstat */
Abind, /* for left-hand-side of bind */
Atodir, /* as in chdir */
Aopen, /* for i/o */
Amount, /* to be mounted or mounted upon */
Acreate, /* is to be created */
Aremove, /* will be removed by caller */
COPEN = 0x0001, /* for i/o */
CMSG = 0x0002, /* the message channel for a mount */
/*rsc CCREATE = 0x0004, * permits creation if c->mnt */
CCEXEC = 0x0008, /* close on exec */
CFREE = 0x0010, /* not in use */
CRCLOSE = 0x0020, /* remove on close */
CCACHE = 0x0080, /* client cache */
};
/* struct block flag values */
enum {
BINTR = (1 << 0), /* allocated in interrupt mode. */
Bipck = (1 << 2), /* ip checksum */
Budpck = (1 << 3), /* udp checksum */
Btcpck = (1 << 4), /* tcp checksum */
Bpktck = (1 << 5), /* packet checksum */
};
struct path path;
struct chan chan;
/* Plan 9 Block. */
struct block {
struct block *next;
struct block *list;
uint8_t *rp; /* first unconsumed byte */
uint8_t *wp; /* first empty byte */
uint8_t *lim; /* 1 past the end of the buffer */
uint8_t *base; /* start of the buffer */
void (*free) (struct block *);
uint16_t flag;
uint16_t checksum; /* IP checksum of complete packet (minus media header) */
};
#define BLEN(s) ((s)->wp - (s)->rp)
#define BALLOC(s) ((s)->lim - (s)->base)
/* linux has qstr, plan 9 has path. Path *might* need to go away
* but there's a lot of fish to try here; maybe qstr should go away
* instead? Let's not fret just now. The plan 9 one is a tad more
* capable.
*/
struct path {
struct kref ref;
char *s;
struct chan **mtpt; /* mtpt history */
int len; /* strlen(s) */
int alen; /* allocated length of s */
int mlen; /* number of path elements */
int malen; /* allocated length of mtpt */
};
struct qid {
uint64_t path;
unsigned long vers;
uint8_t type;
};
struct walkqid {
struct chan *clone;
int nqid;
struct qid qid[0];
};
struct dir {
/* system-modified data */
uint16_t type; /* server type */
unsigned int dev; /* server subtype */
/* file data */
struct qid qid; /* unique id from server */
unsigned long mode; /* permissions */
unsigned long atime; /* last read time */
unsigned long mtime; /* last write time */
unsigned long long length; /* file length: see <u.h> */
char *name; /* last element of path */
char *uid; /* owner name */
char *gid; /* group name */
char *muid; /* last modifier name */
};
struct dirtab {
char name[128];
struct qid qid;
unsigned long long length;
long perm;
};
struct errbuf {
struct jmpbuf jmpbuf;
};
struct dev {
int dc;
char *name;
void (*reset) ();
void (*init) ();
void (*shutdown) ();
struct chan *(*attach) (char *path);
struct walkqid *(*walk) (struct chan * from, struct chan * to, char **paths,
int npath);
long (*stat) (struct chan * dir, uint8_t * path, long l);
struct chan *(*open) (struct chan * file, int mode);
void (*create) (struct chan * dir, char *path, int mode, int perm);
void (*close) (struct chan * chan);
long (*read) (struct chan * chan, void *p, long len, int64_t off);
struct block *(*bread) (struct chan * chan, long len, int64_t off);
long (*write) (struct chan * chan, void *p, long len, int64_t off);
long (*bwrite) (struct chan * chan, struct block * b, int64_t off);
void (*remove) (struct chan * chan);
long (*wstat) (struct chan * chan, uint8_t * new, long size);
void (*power) (int control); /* power mgt: power(1) => on, power (0) => off */
int (*config) (int opts, char *command, void *conf); /* returns 0 on error */
char *(*chaninfo) (struct chan *chan, char *ret, size_t ret_l);
};
enum {
NSMAX = 1000,
NSLOG = 7,
NSCACHE = (1 << NSLOG),
};
struct mntwalk { /* state for /proc/#/ns */
int cddone;
struct mhead *mh;
struct mount *cm;
};
struct mnt
{
spinlock_t lock;
/* references are counted using c->ref; channels on this mount point incref(c->mchan) == Mnt.c */
struct chan *c; /* Channel to file service */
struct proc *rip; /* Reader in progress */
struct mntrpc *queue; /* Queue of pending requests on this channel */
unsigned int id; /* Multiplexer id for channel check */
struct mnt *list; /* Free list */
int flags; /* cache */
int msize; /* data + IOHDRSZ */
char *version; /* 9P version */
struct queue *q; /* input queue */
};
struct mount {
int mountid;
struct mount *next;
struct mhead *head;
struct mount *copy;
struct mount *order;
struct chan *to; /* channel replacing channel (mounted on in linux parlance) */
int mflag;
char *spec;
};
struct mhead {
struct kref ref;
rwlock_t lock;
struct chan *from; /* channel mounted upon */
struct mount *mount; /* what's mounted upon it */
struct mhead *hash; /* Hash chain */
};
/* pgrps are only used at this point to share name spaces.
*/
enum {
MNTLOG = 5,
MNTHASH = 1 << MNTLOG, /* Hash to walk mount table */
NFD = 100, /* per process file descriptors */
};
#define MOUNTH(p,qid) ((p)->mnthash[(qid).path&((1<<MNTLOG)-1)])
struct pgrp {
struct kref ref; /* also used as a lock when mounting */
int noattach;
unsigned long pgrpid;
spinlock_t debug; /* single access via devproc.c */
rwlock_t ns; /* Namespace n read/one write lock */
struct mhead *mnthash[MNTHASH];
};
struct chan {
struct kref ref;
spinlock_t lock;
struct chan *next; /* allocation */
struct chan *link;
int64_t offset; /* in fd */
int64_t devoffset; /* in underlying device; see read */
struct dev *dev;
unsigned int devno;
uint16_t mode; /* read/write */
uint16_t flag;
struct qid qid;
int fid; /* for devmnt */
unsigned long iounit; /* chunk size for i/o; 0==default */
struct mhead *umh; /* mount point that derived struct chan; used in unionread */
struct chan *umc; /* channel in union; held for union read */
// need a queued lock not a spin lock. QLock umqlock; /* serialize unionreads */
qlock_t umqlock;
int uri; /* union read index */
int dri; /* devdirread index */
unsigned char *dirrock; /* directory entry rock for translations */
int nrock;
int mrock;
qlock_t rockqlock;
int ismtpt;
int mc;
//Mntcache*mc; /* Mount cache pointer */
struct mnt *mux; /* Mnt for clients using me for messages */
union {
void *aux;
struct qid pgrpid; /* for #p/notepg */
unsigned long mid; /* for ns in devproc */
};
struct chan *mchan; /* channel to mounted server */
struct qid mqid; /* qid of root of mount point */
struct path *path;
};
/* TODO: consider embedding this in struct proc */
struct fgrp {
spinlock_t lock;
int mountid;
struct kref ref;
struct chan **fd;
int nfd; /* number allocated */
int maxfd; /* highest fd in use */
int exceed; /* debugging */
bool closed;
};
/*
* IO queues
*/
#if 1
struct queue
{
spinlock_t lock;
struct block* bfirst; /* buffer */
struct block* blast;
int len; /* bytes allocated to queue */
int dlen; /* data bytes in queue */
int limit; /* max bytes in queue */
int inilim; /* initial limit */
int state;
int noblock; /* true if writes return immediately when q full */
int eof; /* number of eofs read by user */
void (*kick)(void*); /* restart output */
void (*bypass)(void*, struct block*); /* bypass queue altogether */
void* arg; /* argument to kick */
qlock_t rlock; /* mutex for reading processes */
struct rendez rr; /* process waiting to read */
qlock_t wlock; /* mutex for writing processes */
struct rendez wr; /* process waiting to write */
char err[ERRMAX];
};
#else
struct queue {
spinlock_t lock;
/* short name to make debugging simpler. Leave empty if you wish. */
char name[32];
struct atomic_pipe pipe;
/* we need this placeholder which we manipulate
* to concat/pullup blocks.
*/
struct block *head;
int len;
int limit;
int inilim;
int dlen; /* data bytes in queue */
int state;
int noblock; /* true if writes return immediately when q full */
int eof; /* number of eofs read by user */
void (*kick) (void *); /* restart output */
void (*bypass) (void *, struct block *); /* bypass queue altogether */
void *arg; /* argument to kick */
qlock_t rlock; /* mutex for reading processes */
/* how do we do this Rendez rr; / * process waiting to read */
qlock_t wlock; /* mutex for writing processes */
char err[ERRMAX];
};
#endif
/* device configuration functions for newer drivers from Inferno */
/*
* hardware info about a device
*/
struct devport {
unsigned long port;
int size;
};
struct DevConf
{
unsigned long intnum; /* interrupt number */
char *type; /* card type, malloced */
int nports; /* Number of ports */
struct devport *ports; /* The ports themselves */
};
extern unsigned int qiomaxatomic;
typedef int devgen_t(struct chan *c, char *name, struct dirtab *dirtab, int,
int, struct dir *);
extern char Enoerror[]; /* no error */
extern char Emount[]; /* inconsistent mount */
extern char Eunmount[]; /* not mounted */
extern char Eismtpt[]; /* is a mount point */
extern char Eunion[]; /* not in union */
extern char Emountrpc[]; /* mount rpc error */
extern char Eshutdown[]; /* device shut down */
extern char Enocreate[]; /* mounted directory forbids creation */
extern char Enonexist[]; /* file does not exist */
extern char Eexist[]; /* file already exists */
extern char Ebadsharp[]; /* unknown device in # filename */
extern char Enotdir[]; /* not a directory */
extern char Eisdir[]; /* file is a directory */
extern char Ebadchar[]; /* bad character in file name */
extern char Efilename[]; /* file name syntax */
extern char Eperm[]; /* permission denied */
extern char Ebadusefd[]; /* inappropriate use of fd */
extern char Ebadarg[]; /* bad arg in system call */
extern char Einuse[]; /* device or object already in use */
extern char Eio[]; /* i/o error */
extern char Etoobig[]; /* read or write too large */
extern char Etoosmall[]; /* read or write too small */
extern char Enoport[]; /* network port not available */
extern char Ehungup[]; /* i/o on hungup channel */
extern char Ebadctl[]; /* bad process or channel control request */
extern char Enodev[]; /* no free devices */
extern char Eprocdied[]; /* process exited */
extern char Enochild[]; /* no living children */
extern char Eioload[]; /* i/o error in demand load */
extern char Enovmem[]; /* virtual memory allocation failed */
extern char Ebadfd[]; /* fd out of range or not open */
extern char Enofd[]; /* no free file descriptors */
extern char Eisstream[]; /* seek on a stream */
extern char Ebadexec[]; /* exec header invalid */
extern char Etimedout[]; /* connection timed out */
extern char Econrefused[]; /* connection refused */
extern char Econinuse[]; /* connection in use */
extern char Eintr[]; /* interrupted */
extern char Enomem[]; /* kernel allocate failed */
extern char Enoswap[]; /* swap space full */
extern char Esoverlap[]; /* segments overlap */
extern char Eshort[]; /* i/o count too small */
extern char Egreg[]; /* ken has left the building */
extern char Ebadspec[]; /* bad attach specifier */
extern char Enoreg[]; /* process has no saved registers */
extern char Enoattach[]; /* mount/attach disallowed */
extern char Eshortstat[]; /* stat buffer too small */
extern char Ebadstat[]; /* malformed stat buffer */
extern char Enegoff[]; /* negative i/o offset */
extern char Ecmdargs[]; /* wrong #args in control message */
extern char Ebadip[]; /* bad ip address syntax */
extern char Edirseek[]; /* seek in directory */
/* add 1 in case they forget they need an entry for the passed-in errbuf */
#define ERRSTACK(x) struct errbuf *prev_errbuf; struct errbuf errstack[(x)]; \
int curindex = 0;
#define waserror() (errpush(errstack, ARRAY_SIZE(errstack), &curindex, \
&prev_errbuf) || \
setjmp(&(get_cur_errbuf()->jmpbuf)))
#define error(x,...) {set_errstr(x, ##__VA_ARGS__); \
longjmp(&get_cur_errbuf()->jmpbuf, (void *)x);}
#define nexterror() {errpop(errstack, ARRAY_SIZE(errstack), &curindex, \
prev_errbuf); \
longjmp(&(get_cur_errbuf())->jmpbuf, (void *)1);}
#define poperror() {errpop(errstack, ARRAY_SIZE(errstack), &curindex, \
prev_errbuf);}
/* this would be useful at some point ... */
static inline uintptr_t getcallerpc(void *unused)
{
return 0;
}
void kstrcpy(char *s, char *t, int ns);
/* kern/src/chan.c */
int findmount(struct chan **cp, struct mhead **mp, int dc, unsigned int devno,
struct qid qid);
int eqchanddq(struct chan *c, int dc, unsigned int devno, struct qid qid,
int skipvers);
char *chanpath(struct chan *c);
int isdotdot(char *p);
int emptystr(char *s);
void kstrdup(char **p, char *s);
struct chan *newchan(void);
struct path *newpath(char *s);
void pathclose(struct path *p);
void chanfree(struct chan *c);
void cclose(struct chan *c);
void ccloseq(struct chan *c);
struct chan *cunique(struct chan *c);
int eqqid(struct qid a, struct qid b);
struct mhead *newmhead(struct chan *from);
int cmount(struct chan **newp, struct chan *old, int flag, char *spec);
void cunmount(struct chan *mnt, struct chan *mounted);
struct chan *cclone(struct chan *c);
int walk(struct chan **cp, char **names, int nnames, int nomount, int *nerror);
struct chan *createdir(struct chan *c, struct mhead *mh);
struct chan *namec(char *aname, int amode, int omode, int perm);
char *skipslash(char *name);
void validname(char *aname, int slashok);
char *validnamedup(char *aname, int slashok);
void isdir(struct chan *c);
void putmhead(struct mhead *mh);
/* plan9.c */
char *validname0(char *aname, int slashok, int dup, uintptr_t pc);
/* cleanname.c */
char *cleanname(char *name);
/* kern/src/pgrp.c */
struct fgrp *dupfgrp(struct fgrp *f);
void pgrpinsert(struct mount **order, struct mount *m);
void forceclosefgrp(void);
struct mount *newmount(struct mhead *mh, struct chan *to, int flag, char *spec);
void mountfree(struct mount *m);
void resrcwait(char *reason);
struct pgrp *newpgrp(void);
/* kern/src/devtabc */
void devtabreset();
void devtabinit();
void devtabshutdown();
struct dev *devtabget(int dc, int user);
long devtabread(struct chan *, void *buf, long n, int64_t off);
/* kern/src/allocplan9block.c */
struct block *allocb(int size);
struct block *iallocb(int size);
void freeb(struct block *b);
void checkb(struct block *b, char *msg);
void iallocsummary(void);
/* kern/src/dev.c */
int devgen(struct chan *c, char *name, struct dirtab *tab, int ntab, int i,
struct dir *dp);
void mkqid(struct qid *q, int64_t path, uint32_t vers, int type);
void devdir(struct chan *c, struct qid qid, char *n, int64_t length, char *user,
long perm, struct dir *db);
void devreset();
void devinit();
void devshutdown();
struct chan *devattach(int dc, char *spec);
struct chan *devclone(struct chan *c);
struct walkqid *devwalk(struct chan *c, struct chan *nc, char **name, int nname,
struct dirtab *tab, int ntab, devgen_t * gen);
long devstat(struct chan *c, uint8_t * db, long n, struct dirtab *tab, int ntab,
devgen_t * gen);
long devdirread(struct chan *c, char *d, long n, struct dirtab *tab, int ntab,
devgen_t * gen);
void devpermcheck(char *fileuid, int perm, int omode);
struct chan *devopen(struct chan *c, int omode, struct dirtab *tab, int ntab,
devgen_t * gen);
void devcreate(struct chan *a, char *b, int c, int d);
struct block *devbread(struct chan *c, long n, int64_t offset);
long devbwrite(struct chan *c, struct block *bp, int64_t offset);
void devremove(struct chan *c);
long devwstat(struct chan *c, uint8_t * a, long b);
void devpower(int onoff);
int devconfig(int a, char *b, void *v);
char *devchaninfo(struct chan *chan, char *ret, size_t ret_l);
/* kern/src/plan9file.c */
struct chan *fdtochan(int fd, int mode, int chkmnt, int iref);
void validstat(uint8_t *s, unsigned long n);
int openmode(int omode);
long sysread(int fd, void *p, size_t n, off_t off);
long syswrite(int fd, void *p, size_t n, off_t off);
int sysstat(char *name, uint8_t * statbuf, int len);
int sysfstat(int fd, uint8_t * statbuf, int len);
int sysopen(char *name, int omode);
int syspipe(int *fd);
int sysclose(int fd);
int sysdup(int ofd, int nfd);
int bindmount(int ismount, int fd, int afd,
char* arg0, char* arg1, int flag, char* spec);
int sysunmount(char *name, char *old);
int plan9setup(struct proc *new_proc, struct proc *parent);
int readmem(unsigned long offset, char *buf, unsigned long n,
void *mem, size_t len);
long readstr(long offset, char *buf, long n, char *str);
int readnum(unsigned long off, char *buf, unsigned long n, unsigned long val,
int size);
void close_9ns_files(struct proc *p, bool only_cloexec);
void print_chaninfo(struct chan *ch);
void print_9ns_files(struct proc *p);
/* ker/src/err.c */
int errpush(struct errbuf *errstack, int stacksize, int *curindex,
struct errbuf **prev_errbuf);
void errpop(struct errbuf *errstack, int stacksize, int *curindex,
struct errbuf *prev_errbuf);
/* kern/src/qio.c */
void ixsummary(void);
void freeblist(struct block *b);
struct block *padblock(struct block *bp, int size);
int blocklen(struct block *bp);
int blockalloclen(struct block *bp);
struct block *concatblock(struct block *bp);
struct block *pullupblock(struct block *bp, int n);
struct block *pullupqueue(struct queue *q, int n);
struct block *trimblock(struct block *bp, int offset, int len);
struct block *copyblock(struct block *bp, int count);
struct block *adjustblock(struct block *bp, int len);
int pullblock(struct block **bph, int count);
struct block *qhead(struct queue *q);
struct block *qget(struct queue *q);
int qdiscard(struct queue *q, int len);
int qconsume(struct queue *q, void *vp, int len);
int qpass(struct queue *q, struct block *b);
int qpassnolim(struct queue *q, struct block *b);
struct block *packblock(struct block *bp);
int qproduce(struct queue *q, void *vp, int len);
struct block *qcopy(struct queue *q, int len, uint32_t offset);
struct queue *qopen(int nblock, int msg, void (*kick) (void *), void *arg);
struct queue *qbypass(void (*bypass) (void *, struct block *), void *arg);
void qaddlist(struct queue *q, struct block *b);
struct block *qremove(struct queue *q);
struct block *bl2mem(uint8_t * p, struct block *b, int n);
struct block *mem2bl(uint8_t * p, int len);
void qputback(struct queue *q, struct block *b);
struct block *qbread(struct queue *q, int len);
long qread(struct queue *q, void *vp, int len);
long qbwrite(struct queue *q, struct block *b);
int qwrite(struct queue *q, void *vp, int len);
int qiwrite(struct queue *q, void *vp, int len);
void qclose(struct queue *q);
void qfree(struct queue *q);
void qhangup(struct queue *q, char *msg);
int qisclosed(struct queue *q);
void qreopen(struct queue *q);
int qlen(struct queue *q);
int qwindow(struct queue *q);
int qcanread(struct queue *q);
void qsetlimit(struct queue *q, int limit);
void qnoblock(struct queue *q, int onoff);
void qflush(struct queue *q);
int qfull(struct queue *q);
int qstate(struct queue *q);
/* xdr */
unsigned int convM2D(uint8_t * buf, unsigned int nbuf, struct dir *d,
char *strs);
unsigned int sizeD2M(struct dir *d);
unsigned int convD2M(struct dir *d, uint8_t * buf, unsigned int nbuf);
/* kern/src/ns/parse.c */
struct cmdbuf *parsecmd(char *p, int n);
void cmderror(struct cmdbuf *cb, char *s);
struct cmdtab *lookupcmd(struct cmdbuf *cb, struct cmdtab *ctab, int nctab);
/* kern/src/ns/tokenize.c */
int gettokens(char *s, char **args, int maxargs, char *sep);
int tokenize(char *s, char **args, int maxargs);
/* ker/src/ns/getfields.c */
int getfields(char *str, char **args, int max, int mflag, char *unused_set);
/* plan 9 has a concept of a hostowner, which is a name. For now, we got with a define. */
#define eve "eve"
#define iseve() (1)
/* functions we need to do something with someday */
#define postnote(...)
#define pexit(...) panic("pexit not implemented")
/* kern/drivers/dev/misc.c */
int nrand(int n);
/* kern/drivers/dev/srv.c */
char*srvname(struct chan *c);
/* kern/drivers/dev/proc.c */
void int2flag(int flag, char *s);
/* kern/drivers/dev/random.c */
uint32_t randomread(void *xp, uint32_t n);
/* include for now.
*/
#include <ip.h>
/* kernel-level IP stuff. */
struct fragment4 {
struct block *blist;
struct fragment4 *next;
uint32_t src;
uint32_t dst;
uint16_t id;
uint32_t age;
};
struct fragment6 {
struct block *blist;
struct fragment6 *next;
uint8_t src[IPaddrlen];
uint8_t dst[IPaddrlen];
unsigned int id;
uint32_t age;
};
struct Ipfrag {
uint16_t foff;
uint16_t flen;
uint8_t payload[];
};
#define IPFRAGSZ offsetof(struct Ipfrag, payload[0])
#define CLASS(p) ((*(uint8_t*)(p))>>6)
/* an instance of struct IP */
struct IP {
uint64_t stats[Nipstats];
qlock_t fraglock4;
struct fragment4 *flisthead4;
struct fragment4 *fragfree4;
struct kref id4;
qlock_t fraglock6;
struct fragment6 *flisthead6;
struct fragment6 *fragfree6;
struct kref id6;
int iprouting; /* true if we route like a gateway */
};
/* on the wire packet header */
struct Ip4hdr {
uint8_t vihl; /* Version and header length */
uint8_t tos; /* Type of service */
uint8_t length[2]; /* packet length */
uint8_t id[2]; /* ip->identification */
uint8_t frag[2]; /* Fragment information */
uint8_t ttl; /* Time to live */
uint8_t proto; /* struct protocol */
uint8_t cksum[2]; /* Header checksum */
uint8_t src[4]; /* struct IP source */
uint8_t dst[4]; /* struct IP destination */
};
/*
* one per conversation directory
*/
struct conv {
qlock_t qlock;
int x; /* conversation index */
struct proto *p;
int restricted; /* remote port is restricted */
unsigned int ttl; /* max time to live */
unsigned int tos; /* type of service */
int ignoreadvice; /* don't terminate connection on icmp errors */
uint8_t ipversion;
uint8_t laddr[IPaddrlen]; /* local struct struct IP address */
uint8_t raddr[IPaddrlen]; /* remote struct struct IP address */
uint16_t lport; /* local port number */
uint16_t rport; /* remote port number */
char *owner; /* protections */
int perm;
int inuse; /* opens of listen/data/ctl */
int length;
int state;
int maxfragsize; /* If set, used for fragmentation */
/* udp specific */
int headers; /* data src/dst headers in udp */
int reliable; /* true if reliable udp */
struct conv *incall; /* calls waiting to be listened for */
struct conv *next;
struct queue *rq; /* queued data waiting to be read */
struct queue *wq; /* queued data waiting to be written */
struct queue *eq; /* returned error packets */
struct queue *sq; /* snooping queue */
struct kref snoopers; /* number of processes with snoop open */
qlock_t car;
struct rendez cr; /* looks to be unused... */
char cerr[ERRMAX];
qlock_t listenq;
struct rendez listenr;
struct Ipmulti *multi; /* multicast bindings for this interface */
void *ptcl; /* protocol specific stuff */
struct route *r; /* last route used */
uint32_t rgen; /* routetable generation for *r */
};
struct medium {
char *name;
int hsize; /* medium header size */
int mintu; /* default min mtu */
int maxtu; /* default max mtu */
int maclen; /* mac address length */
void (*bind) (struct ipifc *, int, char **);
void (*unbind) (struct ipifc *);
void (*bwrite) (struct ipifc * ifc, struct block * b, int version,
uint8_t * ip);
/* for arming interfaces to receive multicast */
void (*addmulti) (struct ipifc * ifc, uint8_t * a, uint8_t * ia);
void (*remmulti) (struct ipifc * ifc, uint8_t * a, uint8_t * ia);
/* process packets written to 'data' */
void (*pktin) (struct fs * f, struct ipifc * ifc, struct block * bp);
/* routes for router boards */
void (*addroute) (struct ipifc * ifc, int, uint8_t *, uint8_t *, uint8_t *,
int);
void (*remroute) (struct ipifc * ifc, int, uint8_t *, uint8_t *);
void (*flushroutes) (struct ipifc * ifc);
/* for routing multicast groups */
void (*joinmulti) (struct ipifc * ifc, uint8_t * a, uint8_t * ia);
void (*leavemulti) (struct ipifc * ifc, uint8_t * a, uint8_t * ia);
/* address resolution */
void (*ares) (struct fs *, int, uint8_t *, uint8_t *, int, int); /* resolve */
void (*areg) (struct ipifc *, uint8_t *); /* register */
/* v6 address generation */
void (*pref2addr) (uint8_t * pref, uint8_t * ea);
int unbindonclose; /* if non-zero, unbind on last close */
};
struct ipifc {
spinlock_t lock;
rwlock_t rwlock;
struct conv *conv; /* link to its conversation structure */
char dev[64]; /* device we're attached to */
struct medium *medium; /* Media pointer */
int maxtu; /* Maximum transfer unit */
int mintu; /* Minumum tranfer unit */
int mbps; /* megabits per second */
void *arg; /* medium specific */
int reassemble; /* reassemble struct IP packets before forwarding */
/* these are used so that we can unbind on the fly */
spinlock_t idlock;
uint8_t ifcid; /* incremented each 'bind/unbind/add/remove' */
int ref; /* number of proc's using this ipifc */
//Rendez wait; /* where unbinder waits for ref == 0 */
int unbinding;
uint8_t mac[MAClen]; /* MAC address */
struct iplifc *lifc; /* logical interfaces on this physical one */
uint32_t in, out; /* message statistics */
uint32_t inerr, outerr; /* ... */
uint8_t sendra6; /* flag: send router advs on this ifc */
uint8_t recvra6; /* flag: recv router advs on this ifc */
struct routerparams rp; /* router parameters as in RFC 2461, pp.40—43.
used only if node is router */
};
/* logical interface associated with a physical one */
struct iplifc {
uint8_t local[IPaddrlen];
uint8_t mask[IPaddrlen];
uint8_t remote[IPaddrlen];
uint8_t net[IPaddrlen];
uint8_t tentative; /* =1 => v6 dup disc on, =0 => confirmed unique */
uint8_t onlink; /* =1 => onlink, =0 offlink. */
uint8_t autoflag; /* v6 autonomous flag */
long validlt; /* v6 valid lifetime */
long preflt; /* v6 preferred lifetime */
long origint; /* time when addr was added */
struct Iplink *link; /* addresses linked to this lifc */
struct iplifc *next;
};
/* binding twixt struct Ipself and struct iplifc */
struct Iplink {
struct Ipself *self;
struct iplifc *lifc;
struct Iplink *selflink; /* next link for this local address */
struct Iplink *lifclink; /* next link for this ifc */
uint32_t expire;
struct Iplink *next; /* free list */
struct kref ref;
};
/*
* one per multicast-lifc pair used by a struct conv
*/
struct Ipmulti {
uint8_t ma[IPaddrlen];
uint8_t ia[IPaddrlen];
struct Ipmulti *next;
};
/*
* hash table for 2 ip addresses + 2 ports
*/
enum {
Nipht = 521, /* convenient prime */
IPmatchexact = 0, /* match on 4 tuple */
IPmatchany, /* *!* */
IPmatchport, /* *!port */
IPmatchaddr, /* addr!* */
IPmatchpa, /* addr!port */
};
struct iphash {
struct iphash *next;
struct conv *c;
int match;
};
struct Ipht {
spinlock_t lock;
rwlock_t rwlock;
struct iphash *tab[Nipht];
};
void iphtadd(struct Ipht *, struct conv *);
void iphtrem(struct Ipht *, struct conv *);
struct conv *iphtlook(struct Ipht *ht, uint8_t * sa, uint16_t sp, uint8_t * da,
uint16_t dp);
/*
* one per multiplexed protocol
*/
struct proto {
qlock_t qlock;
char *name; /* protocol name */
int x; /* protocol index */
int ipproto; /* ip protocol type */
char *(*connect) (struct conv *, char **, int);
char *(*announce) (struct conv *, char **, int);
char *(*bind) (struct conv *, char **, int);
int (*state) (struct conv *, char *, int);
void (*create) (struct conv *);
void (*close) (struct conv *);
void (*rcv) (struct proto *, struct ipifc *, struct block *);
char *(*ctl) (struct conv *, char **, int);
void (*advise) (struct proto *, struct block *, char *);
int (*stats) (struct proto *, char *, int);
int (*local) (struct conv *, char *, int);
int (*remote) (struct conv *, char *, int);
int (*inuse) (struct conv *);
int (*gc) (struct proto *); /* returns true if any conversations are freed */
void (*newconv) (struct proto *, struct conv *);
struct fs *f; /* file system this proto is part of */
struct conv **conv; /* array of conversations */
int ptclsize; /* size of per protocol ctl block */
int nc; /* number of conversations */
int ac;
struct qid qid; /* qid for protocol directory */
uint16_t nextrport;
void *priv;
};
/*
* one per struct IP protocol stack
*/
struct fs {
rwlock_t rwlock;
int dev;
int np;
struct proto *p[Maxproto + 1]; /* list of supported protocols */
struct proto *t2p[256]; /* vector of all protocols */
struct proto *ipifc; /* kludge for ipifcremroute & ipifcaddroute */
struct proto *ipmux; /* kludge for finding an ip multiplexor */
struct IP *ip;
struct Ipselftab *self;
struct arp *arp;
struct v6params *v6p;
struct route *v4root[1 << Lroot]; /* v4 routing forest */
struct route *v6root[1 << Lroot]; /* v6 routing forest */
struct route *queue; /* used as temp when reinjecting routes */
struct netlog *alog;
char ndb[1024]; /* an ndb entry for this interface */
int ndbvers;
long ndbmtime;
};
/* one per default router known to host */
struct v6router {
uint8_t inuse;
struct ipifc *ifc;
int ifcid;
uint8_t routeraddr[IPaddrlen];
long ltorigin;
struct routerparams rp;
};
struct v6params {
struct routerparams rp; /* v6 params, one copy per node now */
struct hostparams hp;
struct v6router v6rlist[3]; /* max 3 default routers, currently */
int cdrouter; /* uses only v6rlist[cdrouter] if */
/* cdrouter >= 0. */
};
/*
* logging
*/
enum {
Logip = 1 << 1,
Logtcp = 1 << 2,
Logfs = 1 << 3,
Logicmp = 1 << 5,
Logudp = 1 << 6,
Logcompress = 1 << 7,
Loggre = 1 << 9,
Logppp = 1 << 10,
Logtcprxmt = 1 << 11,
Logigmp = 1 << 12,
Logudpmsg = 1 << 13,
Logipmsg = 1 << 14,
Logrudp = 1 << 15,
Logrudpmsg = 1 << 16,
Logesp = 1 << 17,
Logtcpwin = 1 << 18,
};
/*
* iproute.c
*/
enum {
/* type bits */
Rv4 = (1 << 0), /* this is a version 4 route */
Rifc = (1 << 1), /* this route is a directly connected interface */
Rptpt = (1 << 2), /* this route is a pt to pt interface */
Runi = (1 << 3), /* a unicast self address */
Rbcast = (1 << 4), /* a broadcast self address */
Rmulti = (1 << 5), /* a multicast self address */
Rproxy = (1 << 6), /* this route should be proxied */
};
struct routewalk {
int o;
int h;
char *p;
char *e;
void *state;
void (*walk) (struct route *, struct routewalk *);
};
struct routeTree {
struct route *right;
struct route *left;
struct route *mid;
uint8_t depth;
uint8_t type;
uint8_t ifcid; /* must match ifc->id */
struct ipifc *ifc;
char tag[4];
struct kref ref;
};
struct V4route {
uint32_t address;
uint32_t endaddress;
uint8_t gate[IPv4addrlen];
};
struct V6route {
uint32_t address[IPllen];
uint32_t endaddress[IPllen];
uint8_t gate[IPaddrlen];
};
struct route {
struct routeTree routeTree;
union {
struct V6route v6;
struct V4route v4;
};
};
/*
* Hanging off every ip channel's ->aux is the following structure.
* It maintains the state used by devip and iproute.
*/
struct IPaux {
char *owner; /* the user that did the attach */
char tag[4];
};
extern struct IPaux *newipaux(char *, char *);
/*
* arp.c
*/
struct arpent {
uint8_t ip[IPaddrlen];
uint8_t mac[MAClen];
struct medium *type; /* media type */
struct arpent *hash;
struct block *hold;
struct block *last;
unsigned int ctime; /* time entry was created or refreshed */
unsigned int utime; /* time entry was last used */
uint8_t state;
struct arpent *nextrxt; /* re-transmit chain */
unsigned int rtime; /* time for next retransmission */
uint8_t rxtsrem;
struct ipifc *ifc;
uint8_t ifcid; /* must match ifc->id */
};
#define ipmove(x, y) memmove(x, y, IPaddrlen)
#define ipcmp(x, y) ( (x)[IPaddrlen-1] != (y)[IPaddrlen-1] || memcmp(x, y, IPaddrlen) )
extern uint8_t IPv4bcast[IPaddrlen];
extern uint8_t IPv4bcastobs[IPaddrlen];
extern uint8_t IPv4allsys[IPaddrlen];
extern uint8_t IPv4allrouter[IPaddrlen];
extern uint8_t IPnoaddr[IPaddrlen];
extern uint8_t v4prefix[IPaddrlen];
extern uint8_t IPallbits[IPaddrlen];
#define NOW tsc2msec(read_tsc())
#define seconds() tsc2sec(read_tsc())
/*
* media
*/
extern struct medium ethermedium;
extern struct medium nullmedium;
extern struct medium pktmedium;
extern uint8_t v6allnodesN[IPaddrlen];
extern uint8_t v6allnodesL[IPaddrlen];
extern uint8_t v6allroutersN[IPaddrlen];
extern uint8_t v6allroutersL[IPaddrlen];
extern uint8_t v6allnodesNmask[IPaddrlen];
extern uint8_t v6allnodesLmask[IPaddrlen];
extern uint8_t v6solicitednode[IPaddrlen];
extern uint8_t v6solicitednodemask[IPaddrlen];
extern uint8_t v6Unspecified[IPaddrlen];
extern uint8_t v6loopback[IPaddrlen];
extern uint8_t v6loopbackmask[IPaddrlen];
extern uint8_t v6linklocal[IPaddrlen];
extern uint8_t v6linklocalmask[IPaddrlen];
extern uint8_t v6multicast[IPaddrlen];
extern uint8_t v6multicastmask[IPaddrlen];
extern int v6llpreflen;
extern int v6mcpreflen;
extern int v6snpreflen;
extern int v6aNpreflen;
extern int v6aLpreflen;
extern int ReTransTimer;
void ipv62smcast(uint8_t *, uint8_t *);
void icmpns(struct fs *f, uint8_t* src, int suni, uint8_t* targ, int tuni,
uint8_t* mac);
void icmpna(struct fs *f, uint8_t* src, uint8_t* dst, uint8_t* targ, uint8_t* mac,
uint8_t flags);
void icmpttlexceeded6(struct fs *f, struct ipifc *ifc, struct block *bp);
void icmppkttoobig6(struct fs *f, struct ipifc *ifc, struct block *bp);
void icmphostunr(struct fs *f, struct ipifc *ifc,
struct block *bp, int code, int free);
static inline int abs(int x)
{
if (x < 0)
return -x;
return x;
}
/* kern/src/net/nixip/arp.c */
void arpinit(struct fs *f);
void cleanarpent(struct arp *arp, struct arpent *a);
struct arpent *arpget(struct arp *arp, struct block *bp, int version, struct ipifc *ifc, uint8_t *ip, uint8_t *mac);
void arprelease(struct arp *arp, struct arpent *arpent);
struct block *arpresolve(struct arp *arp, struct arpent *a, struct medium *type, uint8_t *mac);
void arpenter(struct fs *fs, int version, uint8_t *ip, uint8_t *mac, int n, int refresh);
int arpwrite(struct fs *fs, char *s, int len);
int arpread(struct arp *arp, char *p, uint32_t offset, int len);
int rxmitsols(struct arp *arp);
/* kern/src/net/nixip/chandial.c */
struct chan *chandial(char *dest, char *local, char *dir, struct chan **ctlp);
/* kern/src/net/nixip/devip.c */
struct IPaux *newipaux(char *owner, char *tag);
void closeconv(struct conv *cv);
char *setluniqueport(struct conv *c, int lport);
char *setlport(struct conv *c);
char *setladdrport(struct conv *c, char *str, int announcing);
char *Fsstdconnect(struct conv *c, char *argv[], int argc);
char *Fsstdannounce(struct conv *c, char *argv[], int argc);
char *Fsstdbind(struct conv *c, char *argv[], int argc);
int Fsproto(struct fs *f, struct proto *p);
int Fsbuiltinproto(struct fs *f, uint8_t proto);
struct conv *Fsprotoclone(struct proto *p, char *user);
int Fsconnected(struct conv *c, char *msg);
struct proto *Fsrcvpcol(struct fs *f, uint8_t proto);
struct proto *Fsrcvpcolx(struct fs *f, uint8_t proto);
struct conv *Fsnewcall(struct conv *c, uint8_t *raddr, uint16_t rport, uint8_t *laddr, uint16_t lport, uint8_t version);
long ndbwrite(struct fs *f, char *a, uint32_t off, int n);
uint32_t scalednconv(void);
/* kern/src/net/nixip/ethermedium.c */
void ethermediumlink(void);
/* kern/src/net/nixip/icmp6.c */
void icmpadvise6(struct proto *icmp, struct block *bp, char *msg);
char *icmpctl6(struct conv *c, char **argv, int argc);
void icmpns(struct fs *f, uint8_t *src, int suni, uint8_t *targ, int tuni, uint8_t *mac);
void icmpna(struct fs *f, uint8_t *src, uint8_t *dst, uint8_t *targ, uint8_t *mac, uint8_t flags);
void icmphostunr(struct fs *f, struct ipifc *ifc, struct block *bp, int code, int free);
void icmpttlexceeded6(struct fs *f, struct ipifc *ifc, struct block *bp);
void icmppkttoobig6(struct fs *f, struct ipifc *ifc, struct block *bp);
int icmpstats6(struct proto *icmp6, char *buf, int len);
void icmp6init(struct fs *fs);
/* kern/src/net/nixip/icmp.c */
char *icmpconnect(struct conv *c, char **argv, int argc);
int icmpstate(struct conv *c, char *state, int n);
char *icmpannounce(struct conv *c, char **argv, int argc);
void icmpclose(struct conv *c);
void icmpttlexceeded(struct fs *f, uint8_t *ia, struct block *bp);
void icmpnoconv(struct fs *f, struct block *bp);
void icmpcantfrag(struct fs *f, struct block *bp, int mtu);
void icmpadvise(struct proto *icmp, struct block *bp, char *msg);
int icmpstats(struct proto *icmp, char *buf, int len);
void icmpinit(struct fs *fs);
/* kern/src/net/nixip/ipaux.c */
uint16_t ptclcsum(struct block *bp, int offset, int len);
void ipv62smcast(uint8_t *smcast, uint8_t *a);
int parsemac(uint8_t *to, char *from, int len);
uint32_t iphash(uint8_t *sa, uint16_t sp, uint8_t *da, uint16_t dp);
void iphtadd(struct Ipht *ht, struct conv *c);
void iphtrem(struct Ipht *ht, struct conv *c);
struct conv *iphtlook(struct Ipht *ht, uint8_t *sa, uint16_t sp, uint8_t *da, uint16_t dp);
/* kern/src/net/nixip/ip.c */
void ip_init_6(struct fs *f);
void initfrag(struct IP *ip, int size);
void ip_init(struct fs *f);
void iprouting(struct fs *f, int on);
int ipoput4(struct fs *f, struct block *bp, int gating, int ttl, int tos, struct conv *c);
void ipiput4(struct fs *f, struct ipifc *ifc, struct block *bp);
int ipstats(struct fs *f, char *buf, int len);
struct block *ip4reassemble(struct IP *ip, int offset, struct block *bp, struct Ip4hdr *ih);
void ipfragfree4(struct IP *ip, struct fragment4 *frag);
struct fragment4 *ipfragallo4(struct IP *ip);
uint16_t ipcsum(uint8_t *addr);
/* kern/src/net/nixip/ipifc.c */
void addipmedium(struct medium *med);
struct medium *ipfindmedium(char *name);
char *ipifcsetmtu(struct ipifc *ifc, char **argv, int argc);
char *ipifcadd(struct ipifc *ifc, char **argv, int argc, int tentative, struct iplifc *lifcp);
char *ipifcrem(struct ipifc *ifc, char **argv, int argc);
void ipifcaddroute(struct fs *f, int vers, uint8_t *addr, uint8_t *mask, uint8_t *gate, int type);
void ipifcremroute(struct fs *f, int vers, uint8_t *addr, uint8_t *mask);
char *ipifcra6(struct ipifc *ifc, char **argv, int argc);
int ipifcstats(struct proto *ipifc, char *buf, int len);
void ipifcinit(struct fs *f);
long ipselftabread(struct fs *f, char *cp, uint32_t offset, int n);
int iptentative(struct fs *f, uint8_t *addr);
int ipforme(struct fs *f, uint8_t *addr);
struct ipifc *findipifc(struct fs *f, uint8_t *remote, int type);
int v6addrtype(uint8_t *addr);
void findlocalip(struct fs *f, uint8_t *local, uint8_t *remote);
int ipv4local(struct ipifc *ifc, uint8_t *addr);
int ipv6local(struct ipifc *ifc, uint8_t *addr);
int ipv6anylocal(struct ipifc *ifc, uint8_t *addr);
struct iplifc *iplocalonifc(struct ipifc *ifc, uint8_t *ip);
int ipproxyifc(struct fs *f, struct ipifc *ifc, uint8_t *ip);
int ipismulticast(uint8_t *ip);
int ipisbm(uint8_t *ip);
void ipifcaddmulti(struct conv *c, uint8_t *ma, uint8_t *ia);
void ipifcremmulti(struct conv *c, uint8_t *ma, uint8_t *ia);
char *ipifcadd6(struct ipifc *ifc, char **argv, int argc);
/* kern/src/net/nixip/iproute.c */
void v4addroute(struct fs *f, char *tag, uint8_t *a, uint8_t *mask, uint8_t *gate, int type);
void v6addroute(struct fs *f, char *tag, uint8_t *a, uint8_t *mask, uint8_t *gate, int type);
struct route **looknode(struct route **cur, struct route *r);
void v4delroute(struct fs *f, uint8_t *a, uint8_t *mask, int dolock);
void v6delroute(struct fs *f, uint8_t *a, uint8_t *mask, int dolock);
struct route *v4lookup(struct fs *f, uint8_t *a, struct conv *c);
struct route *v6lookup(struct fs *f, uint8_t *a, struct conv *c);
void routetype(int type, char *p);
void convroute(struct route *r, uint8_t *addr, uint8_t *mask, uint8_t *gate, char *t, int *nifc);
void ipwalkroutes(struct fs *f, struct routewalk *rw);
long routeread(struct fs *f, char *p, uint32_t offset, int n);
void delroute(struct fs *f, struct route *r, int dolock);
int routeflush(struct fs *f, struct route *r, char *tag);
struct route *iproute(struct fs *fs, uint8_t *ip);
long routewrite(struct fs *f, struct chan *c, char *p, int n);
/* kern/src/net/nixip/ipv6.c */
int ipoput6(struct fs *f, struct block *bp, int gating, int ttl, int tos, struct conv *c);
void ipiput6(struct fs *f, struct ipifc *ifc, struct block *bp);
void ipfragfree6(struct IP *ip, struct fragment6 *frag);
struct fragment6 *ipfragallo6(struct IP *ip);
int unfraglen(struct block *bp, uint8_t *nexthdr, int setfh);
struct block *procopts(struct block *bp);
struct block *ip6reassemble(struct IP *ip, int uflen, struct block *bp, struct ip6hdr *ih);
/* kern/src/net/nixip/loopbackmedium.c */
void loopbackmediumlink(void);
/* kern/src/net/nixip/netdevmedium.c */
void netdevmediumlink(void);
/* kern/src/net/nixip/netlog.c */
void netloginit(struct fs *f);
void netlogopen(struct fs *f);
void netlogclose(struct fs *f);
long netlogread(struct fs *f, void *a, uint32_t unused_len, long n);
void netlogctl(struct fs *f, char *s, int n);
void netlog(struct fs *f, int mask, char *fmt, ...);
/* kern/src/net/nixip/nullmedium.c */
void nullmediumlink(void);
/* kern/src/net/nixip/pktmedium.c */
void pktmediumlink(void);
/* kern/src/net/nixip/ptclbsum.c */
uint16_t ptclbsum(uint8_t *addr, int len);
/* kern/src/net/nixip/tcp.c */
void tcpinit(struct fs *fs);
/* kern/src/net/nixip/udp.c */
void udpkick(void *x, struct block *bp);
void udpiput(struct proto *udp, struct ipifc *ifc, struct block *bp);
char *udpctl(struct conv *c, char **f, int n);
void udpadvise(struct proto *udp, struct block *bp, char *msg);
int udpstats(struct proto *udp, char *buf, int len);
void udpinit(struct fs *fs);
/* IP library */
/* kern/src/libip/bo.c */
void hnputv(void *p, uint64_t v);
void hnputl(void *p, unsigned int v);
void hnputs(void *p, uint16_t v);
uint64_t nhgetv(void *p);
unsigned int nhgetl(void *p);
uint16_t nhgets(void *p);
/* kern/src/libip/classmask.c */
uint8_t *defmask(uint8_t *ip);
void maskip(uint8_t *from, uint8_t *mask, uint8_t *to);
/* kern/src/libip/eipfmt.c */
int eipfmt(void *);
/* kern/src/libip/equivip.c */
int equivip4(uint8_t *a, uint8_t *b);
int equivip6(uint8_t *a, uint8_t *b);
/* kern/src/libip/ipaux.c */
int isv4(uint8_t *ip);
void v4tov6(uint8_t *v6, uint8_t *v4);
int v6tov4(uint8_t *v4, uint8_t *v6);
/* kern/src/libip/myetheraddr.c */
int myetheraddr(uint8_t *to, char *dev);
/* kern/src/libip/myipaddr.c */
int myipaddr(uint8_t *ip, char *net);
/* kern/src/libip/parseether.c */
int parseether(uint8_t *to, char *from);
/* kern/src/libip/parseip.c */
char *v4parseip(uint8_t *to, char *from);
int64_t parseip(uint8_t *to, char *from);
int64_t parseipmask(uint8_t *to, char *from);
char *v4parsecidr(uint8_t *addr, uint8_t *mask, char *from);
/* kern/src/libip/ptclbsum.c */
uint16_t ptclbsum(uint8_t *addr, int len);
/* kern/src/libip/readipifc.c */
struct ipifc *readipifc(char *net, struct ipifc *ifc, int index);
#endif /* ROS_KERN_PLAN9_H */