Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <ip.h>
4 #include "dat.h"
5 #include "protos.h"
7 enum
8 {
9 Maxoptlen= 312-4,
11 /* dhcp types */
12 Discover= 1,
13 Offer= 2,
14 Request= 3,
15 Decline= 4,
16 Ack= 5,
17 Nak= 6,
18 Release= 7,
19 Inform= 8,
21 /* bootp option types */
22 OBend= 255,
23 OBpad= 0,
24 OBmask= 1,
25 OBtimeoff= 2,
26 OBrouter= 3,
27 OBtimeserver= 4,
28 OBnameserver= 5,
29 OBdnserver= 6,
30 OBlogserver= 7,
31 OBcookieserver= 8,
32 OBlprserver= 9,
33 OBimpressserver= 10,
34 OBrlserver= 11,
35 OBhostname= 12, /* 0xc0 */
36 OBbflen= 13,
37 OBdumpfile= 14,
38 OBdomainname= 15,
39 OBswapserver= 16, /* 0x10 */
40 OBrootpath= 17,
41 OBextpath= 18,
42 OBipforward= 19,
43 OBnonlocal= 20,
44 OBpolicyfilter= 21,
45 OBmaxdatagram= 22,
46 OBttl= 23,
47 OBpathtimeout= 24,
48 OBpathplateau= 25,
49 OBmtu= 26,
50 OBsubnetslocal= 27,
51 OBbaddr= 28,
52 OBdiscovermask= 29,
53 OBsupplymask= 30,
54 OBdiscoverrouter= 31,
55 OBrsserver= 32, /* 0x20 */
56 OBstaticroutes= 33,
57 OBtrailerencap= 34,
58 OBarptimeout= 35,
59 OBetherencap= 36,
60 OBtcpttl= 37,
61 OBtcpka= 38,
62 OBtcpkag= 39,
63 OBnisdomain= 40,
64 OBniserver= 41,
65 OBntpserver= 42,
66 OBvendorinfo= 43, /* 0x2b */
67 OBnetbiosns= 44,
68 OBnetbiosdds= 45,
69 OBnetbiostype= 46,
70 OBnetbiosscope= 47,
71 OBxfontserver= 48, /* 0x30 */
72 OBxdispmanager= 49,
73 OBnisplusdomain= 64, /* 0x40 */
74 OBnisplusserver= 65,
75 OBhomeagent= 68,
76 OBsmtpserver= 69,
77 OBpop3server= 70,
78 OBnntpserver= 71,
79 OBwwwserver= 72,
80 OBfingerserver= 73,
81 OBircserver= 74,
82 OBstserver= 75,
83 OBstdaserver= 76,
85 /* dhcp options */
86 ODipaddr= 50, /* 0x32 */
87 ODlease= 51,
88 ODoverload= 52,
89 ODtype= 53, /* 0x35 */
90 ODserverid= 54, /* 0x36 */
91 ODparams= 55, /* 0x37 */
92 ODmessage= 56,
93 ODmaxmsg= 57,
94 ODrenewaltime= 58,
95 ODrebindingtime= 59,
96 ODvendorclass= 60,
97 ODclientid= 61, /* 0x3d */
98 ODtftpserver= 66,
99 ODbootfile= 67,
101 /* plan9 vendor info options */
102 OP9fs= 128, /* plan9 file servers */
103 OP9auth= 129, /* plan9 auth servers */
104 };
106 static void
107 p_compile(Filter *f)
109 sysfatal("unknown dhcp field: %s", f->s);
112 /*
113 * convert a byte array to hex
114 */
115 static char
116 hex(int x)
118 if(x < 10)
119 return x + '0';
120 return x - 10 + 'a';
122 static char*
123 phex(char *p, char *e, char *tag, uchar *o, int n)
125 p = seprint(p, e, "%s=", tag);
127 for(; p+2 < e && n > 0; n--){
128 *p++ = hex(*o>>4);
129 *p++ = hex(*o & 0xf);
130 o++;
132 return p;
135 static char*
136 pstring(char *p, char *e, char *tag, uchar *o, int n)
138 char msg[256];
140 if(n > sizeof msg - 1)
141 n = sizeof msg - 1;
142 memmove(msg, o, n);
143 msg[n] = 0;
144 return seprint(p, e, "%s=%s", tag, msg);
147 static char*
148 pint(char *p, char *e, char *tag, uchar *o, int n)
150 int x;
152 x = *(char*)o++;
153 for(; n > 1; n--)
154 x = (x<<8)|*o++;
155 return seprint(p, e, "%s=%d", tag, x);
158 static char*
159 puint(char *p, char *e, char *tag, uchar *o, int n)
161 uint x;
163 x = *o++;
164 for(; n > 1; n--)
165 x = (x<<8)|*o++;
166 return seprint(p, e, "%s=%ud", tag, x);
169 static char*
170 pserver(char *p, char *e, char *tag, uchar *o, int n)
172 p = seprint(p, e, "%s=(", tag);
173 while(n >= 4){
174 p = seprint(p, e, " %V", o);
175 n -= 4;
176 o += 4;
178 p = seprint(p, e, ")");
179 return p;
182 static char *dhcptype[256] =
184 [Discover] "Discover",
185 [Offer] "Offer",
186 [Request] "Request",
187 [Decline] "Decline",
188 [Ack] "Ack",
189 [Nak] "Nak",
190 [Release] "Release",
191 [Inform] "Inform"
192 };
195 static char*
196 ptype(char *p, char *e, uchar val)
198 char *x;
200 x = dhcptype[val];
201 if(x != nil)
202 return seprint(p, e, "t=%s", x);
203 else
204 return seprint(p, e, "t=%d", val);
207 static int
208 p_seprint(Msg *m)
210 int i, n, code;
211 uchar *o, *ps;
212 char *p, *e;
213 char msg[64];
215 /* no next proto */
216 m->pr = nil;
218 p = m->p;
219 e = m->e;
220 ps = m->ps;
222 while(ps < m->pe){
223 code = *ps++;
224 if(code == 255)
225 break;
226 if(code == 0)
227 continue;
229 /* ignore anything that's too long */
230 n = *ps++;
231 o = ps;
232 ps += n;
233 if(ps > m->pe)
234 break;
236 switch(code){
237 case ODipaddr: /* requested ip address */
238 p = pserver(p, e, "ipaddr", o, n);
239 break;
240 case ODlease: /* requested lease time */
241 p = pint(p, e, "lease", o, n);
242 break;
243 case ODtype:
244 p = ptype(p, e, *o);
245 break;
246 case ODserverid:
247 p = pserver(p, e, "serverid", o, n);
248 break;
249 case ODmessage:
250 p = pstring(p, e, "message", o, n);
251 break;
252 case ODmaxmsg:
253 p = puint(p, e, "maxmsg", o, n);
254 break;
255 case ODclientid:
256 p = phex(p, e, "clientid", o, n);
257 break;
258 case ODparams:
259 p = seprint(p, e, " requested=(");
260 for(i = 0; i < n; i++){
261 if(i != 0)
262 p = seprint(p, e, " ");
263 p = seprint(p, e, "%ud", o[i]);
265 p = seprint(p, e, ")");
266 break;
267 case ODvendorclass:
268 p = pstring(p, e, "vendorclass", o, n);
269 break;
270 case OBmask:
271 p = pserver(p, e, "mask", o, n);
272 break;
273 case OBtimeoff:
274 p = pint(p, e, "timeoff", o, n);
275 break;
276 case OBrouter:
277 p = pserver(p, e, "router", o, n);
278 break;
279 case OBtimeserver:
280 p = pserver(p, e, "timesrv", o, n);
281 break;
282 case OBnameserver:
283 p = pserver(p, e, "namesrv", o, n);
284 break;
285 case OBdnserver:
286 p = pserver(p, e, "dnssrv", o, n);
287 break;
288 case OBlogserver:
289 p = pserver(p, e, "logsrv", o, n);
290 break;
291 case OBcookieserver:
292 p = pserver(p, e, "cookiesrv", o, n);
293 break;
294 case OBlprserver:
295 p = pserver(p, e, "lprsrv", o, n);
296 break;
297 case OBimpressserver:
298 p = pserver(p, e, "impresssrv", o, n);
299 break;
300 case OBrlserver:
301 p = pserver(p, e, "rlsrv", o, n);
302 break;
303 case OBhostname:
304 p = pstring(p, e, "hostname", o, n);
305 break;
306 case OBbflen:
307 break;
308 case OBdumpfile:
309 p = pstring(p, e, "dumpfile", o, n);
310 break;
311 case OBdomainname:
312 p = pstring(p, e, "domname", o, n);
313 break;
314 case OBswapserver:
315 p = pserver(p, e, "swapsrv", o, n);
316 break;
317 case OBrootpath:
318 p = pstring(p, e, "rootpath", o, n);
319 break;
320 case OBextpath:
321 p = pstring(p, e, "extpath", o, n);
322 break;
323 case OBipforward:
324 p = phex(p, e, "ipforward", o, n);
325 break;
326 case OBnonlocal:
327 p = phex(p, e, "nonlocal", o, n);
328 break;
329 case OBpolicyfilter:
330 p = phex(p, e, "policyfilter", o, n);
331 break;
332 case OBmaxdatagram:
333 p = phex(p, e, "maxdatagram", o, n);
334 break;
335 case OBttl:
336 p = puint(p, e, "ttl", o, n);
337 break;
338 case OBpathtimeout:
339 p = puint(p, e, "pathtimeout", o, n);
340 break;
341 case OBpathplateau:
342 p = phex(p, e, "pathplateau", o, n);
343 break;
344 case OBmtu:
345 p = puint(p, e, "mtu", o, n);
346 break;
347 case OBsubnetslocal:
348 p = pserver(p, e, "subnet", o, n);
349 break;
350 case OBbaddr:
351 p = pserver(p, e, "baddr", o, n);
352 break;
353 case OBdiscovermask:
354 p = pserver(p, e, "discovermsak", o, n);
355 break;
356 case OBsupplymask:
357 p = pserver(p, e, "rousupplymaskter", o, n);
358 break;
359 case OBdiscoverrouter:
360 p = pserver(p, e, "discoverrouter", o, n);
361 break;
362 case OBrsserver:
363 p = pserver(p, e, "rsrouter", o, n);
364 break;
365 case OBstaticroutes:
366 p = phex(p, e, "staticroutes", o, n);
367 break;
368 case OBtrailerencap:
369 p = phex(p, e, "trailerencap", o, n);
370 break;
371 case OBarptimeout:
372 p = puint(p, e, "arptimeout", o, n);
373 break;
374 case OBetherencap:
375 p = phex(p, e, "etherencap", o, n);
376 break;
377 case OBtcpttl:
378 p = puint(p, e, "tcpttl", o, n);
379 break;
380 case OBtcpka:
381 p = puint(p, e, "tcpka", o, n);
382 break;
383 case OBtcpkag:
384 p = phex(p, e, "tcpkag", o, n);
385 break;
386 case OBnisdomain:
387 p = pstring(p, e, "nisdomain", o, n);
388 break;
389 case OBniserver:
390 p = pserver(p, e, "nisrv", o, n);
391 break;
392 case OBntpserver:
393 p = pserver(p, e, "ntpsrv", o, n);
394 break;
395 case OBvendorinfo:
396 p = phex(p, e, "vendorinfo", o, n);
397 break;
398 case OBnetbiosns:
399 p = pserver(p, e, "biosns", o, n);
400 break;
401 case OBnetbiosdds:
402 p = phex(p, e, "biosdds", o, n);
403 break;
404 case OBnetbiostype:
405 p = phex(p, e, "biostype", o, n);
406 break;
407 case OBnetbiosscope:
408 p = phex(p, e, "biosscope", o, n);
409 break;
410 case OBxfontserver:
411 p = pserver(p, e, "fontsrv", o, n);
412 break;
413 case OBxdispmanager:
414 p = pserver(p, e, "xdispmgr", o, n);
415 break;
416 case OBnisplusdomain:
417 p = pstring(p, e, "nisplusdomain", o, n);
418 break;
419 case OBnisplusserver:
420 p = pserver(p, e, "nisplussrv", o, n);
421 break;
422 case OBhomeagent:
423 p = pserver(p, e, "homeagent", o, n);
424 break;
425 case OBsmtpserver:
426 p = pserver(p, e, "smtpsrv", o, n);
427 break;
428 case OBpop3server:
429 p = pserver(p, e, "pop3srv", o, n);
430 break;
431 case OBnntpserver:
432 p = pserver(p, e, "ntpsrv", o, n);
433 break;
434 case OBwwwserver:
435 p = pserver(p, e, "wwwsrv", o, n);
436 break;
437 case OBfingerserver:
438 p = pserver(p, e, "fingersrv", o, n);
439 break;
440 case OBircserver:
441 p = pserver(p, e, "ircsrv", o, n);
442 break;
443 case OBstserver:
444 p = pserver(p, e, "stsrv", o, n);
445 break;
446 case OBstdaserver:
447 p = pserver(p, e, "stdasrv", o, n);
448 break;
449 case OBend:
450 goto out;
451 default:
452 snprint(msg, sizeof msg, " T%ud", code);
453 p = phex(p, e, msg, o, n);
454 break;
456 if(*ps != OBend)
457 p = seprint(p, e, " ");
459 out:
460 m->p = p;
461 m->ps = ps;
462 return 0;
465 Proto dhcp =
467 "dhcp",
468 p_compile,
469 nil,
470 p_seprint,
471 nil,
472 nil,
473 nil,
474 defaultframer
475 };