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
p_compile(Filter * f)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
p_filter(Filter * f,Msg * m)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*
op(int i)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
p_seprint(Msg * m)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 };
178