plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

bootp.c (3436B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <ip.h>
      4 #include "dat.h"
      5 #include "protos.h"
      6 
      7 enum
      8 {
      9 	OfferTimeout=	60,		/* when an offer times out */
     10 	MaxLease=	60*60,		/* longest lease for dynamic binding */
     11 	MinLease=	15*60,		/* shortest lease for dynamic binding */
     12 	StaticLease=	30*60,		/* lease for static binding */
     13 
     14 	IPUDPHDRSIZE=	28,		/* size of an IP plus UDP header */
     15 	MINSUPPORTED=	576,		/* biggest IP message the client must support */
     16 
     17 	/* lengths of some bootp fields */
     18 	Maxhwlen=	16,
     19 	Maxfilelen=	128,
     20 	Maxoptlen=	312-4,
     21 
     22 	/* bootp types */
     23 	Bootrequest=	1,
     24 	Bootreply= 	2,
     25 
     26 	/* bootp flags */
     27 	Fbroadcast=	1<<15
     28 };
     29 
     30 typedef struct Hdr	Hdr;
     31 struct Hdr
     32 {
     33 	uchar	op;			/* opcode */
     34 	uchar	htype;			/* hardware type */
     35 	uchar	hlen;			/* hardware address len */
     36 	uchar	hops;			/* hops */
     37 	uchar	xid[4];			/* a random number */
     38 	uchar	secs[2];		/* elapsed since client started booting */
     39 	uchar	flags[2];
     40 	uchar	ciaddr[IPv4addrlen];	/* client IP address (client tells server) */
     41 	uchar	yiaddr[IPv4addrlen];	/* client IP address (server tells client) */
     42 	uchar	siaddr[IPv4addrlen];	/* server IP address */
     43 	uchar	giaddr[IPv4addrlen];	/* gateway IP address */
     44 	uchar	chaddr[Maxhwlen];	/* client hardware address */
     45 	char	sname[64];		/* server host name (optional) */
     46 	char	file[Maxfilelen];	/* boot file name */
     47 	uchar	optmagic[4];
     48 	uchar	optdata[Maxoptlen];
     49 };
     50 
     51 enum
     52 {
     53 	Oca,
     54 	Osa,
     55 	Ot
     56 };
     57 
     58 static Field p_fields[] =
     59 {
     60 	{"ca",		Fv4ip,	Oca,	"client IP addr",	} ,
     61 	{"sa",		Fv4ip,	Osa,	"server IP addr",	} ,
     62 	{0}
     63 };
     64 
     65 #define plan9opt ((ulong)(('p'<<24) | ('9'<<16) | (' '<<8) | ' '))
     66 #define genericopt (0x63825363UL)
     67 
     68 static Mux p_mux[] =
     69 {
     70 	{"dhcp", 	genericopt,},
     71 	{"plan9bootp",	plan9opt,},
     72 	{"dump",	0,},
     73 	{0}
     74 };
     75 
     76 static void
     77 p_compile(Filter *f)
     78 {
     79 	Mux *m;
     80 
     81 	if(f->op == '='){
     82 		compile_cmp(arp.name, f, p_fields);
     83 		return;
     84 	}
     85 	for(m = p_mux; m->name != nil; m++)
     86 		if(strcmp(f->s, m->name) == 0){
     87 			f->pr = m->pr;
     88 			f->ulv = m->val;
     89 			f->subop = Ot;
     90 			return;
     91 		}
     92 	sysfatal("unknown bootp field: %s", f->s);
     93 }
     94 
     95 static int
     96 p_filter(Filter *f, Msg *m)
     97 {
     98 	Hdr *h;
     99 
    100 	h = (Hdr*)m->ps;
    101 
    102 	if(m->pe < (uchar*)h->sname)
    103 		return 0;
    104 	m->ps = h->optdata;
    105 
    106 	switch(f->subop){
    107 	case Oca:
    108 		return NetL(h->ciaddr) == f->ulv || NetL(h->yiaddr) == f->ulv;
    109 	case Osa:
    110 		return NetL(h->siaddr) == f->ulv;
    111 	case Ot:
    112 		return NetL(h->optmagic) == f->ulv;
    113 	}
    114 	return 0;
    115 }
    116 
    117 static char*
    118 op(int i)
    119 {
    120 	static char x[20];
    121 
    122 	switch(i){
    123 	case Bootrequest:
    124 		return "Req";
    125 	case Bootreply:
    126 		return "Rep";
    127 	default:
    128 		sprint(x, "%d", i);
    129 		return x;
    130 	}
    131 }
    132 
    133 
    134 static int
    135 p_seprint(Msg *m)
    136 {
    137 	Hdr *h;
    138 	ulong x;
    139 
    140 	h = (Hdr*)m->ps;
    141 
    142 	if(m->pe < (uchar*)h->sname)
    143 		return -1;
    144 
    145 	/* point past data */
    146 	m->ps = h->optdata;
    147 
    148 	/* next protocol */
    149 	m->pr = nil;
    150 	if(m->pe >= (uchar*)h->optdata){
    151 		x = NetL(h->optmagic);
    152 		demux(p_mux, x, x, m, &dump);
    153 	}
    154 
    155 	m->p = seprint(m->p, m->e, "t=%s ht=%d hl=%d hp=%d xid=%ux sec=%d fl=%4.4ux ca=%V ya=%V sa=%V ga=%V cha=%E magic=%lux",
    156 		op(h->op), h->htype, h->hlen, h->hops,
    157 		NetL(h->xid), NetS(h->secs), NetS(h->flags),
    158 		h->ciaddr, h->yiaddr, h->siaddr, h->giaddr, h->chaddr,
    159 		(ulong)NetL(h->optmagic));
    160 	if(m->pe > (uchar*)h->sname && *h->sname)
    161 		m->p = seprint(m->p, m->e, " snam=%s", h->sname);
    162 	if(m->pe > (uchar*)h->file && *h->file)
    163 		m->p = seprint(m->p, m->e, " file=%s", h->file);
    164 	return 0;
    165 }
    166 
    167 Proto bootp =
    168 {
    169 	"bootp",
    170 	p_compile,
    171 	p_filter,
    172 	p_seprint,
    173 	p_mux,
    174 	"%#.8lux",
    175 	p_fields,
    176 	defaultframer
    177 };