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 Maxoptlen= 312-4,
10
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,
20
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,
84
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,
100
101 /* plan9 vendor info options */
102 OP9fsv4= 128, /* plan9 file servers */
103 OP9authv4= 129, /* plan9 auth servers */
104 };
105
106 /*
107 * convert a byte array to hex
108 */
109 static char
hex(int x)110 hex(int x)
111 {
112 if(x < 10)
113 return x + '0';
114 return x - 10 + 'a';
115 }
116 static char*
phex(char * p,char * e,char * tag,uchar * o,int n)117 phex(char *p, char *e, char *tag, uchar *o, int n)
118 {
119 p = seprint(p, e, "%s=", tag);
120
121 for(; p+2 < e && n > 0; n--){
122 *p++ = hex(*o >> 4);
123 *p++ = hex(*o & 0xf);
124 o++;
125 }
126 return p;
127 }
128
129 static char*
pstring(char * p,char * e,char * tag,uchar * o,int n)130 pstring(char *p, char *e, char *tag, uchar *o, int n)
131 {
132 char msg[256];
133
134 if(n > sizeof msg - 1)
135 n = sizeof msg - 1;
136 memmove(msg, o, n);
137 msg[n] = 0;
138 return seprint(p, e, "%s=%s", tag, msg);
139 }
140
141 static char*
pint(char * p,char * e,char * tag,uchar * o,int n)142 pint(char *p, char *e, char *tag, uchar *o, int n)
143 {
144 int x;
145
146 x = *(char*)o++;
147 for(; n > 1; n--)
148 x = x<<8 | *o++;
149 return seprint(p, e, "%s=%d", tag, x);
150 }
151
152 static char*
puint(char * p,char * e,char * tag,uchar * o,int n)153 puint(char *p, char *e, char *tag, uchar *o, int n)
154 {
155 uint x;
156
157 x = *o++;
158 for(; n > 1; n--)
159 x = x<<8 | *o++;
160 return seprint(p, e, "%s=%ud", tag, x);
161 }
162
163 static char*
pserver(char * p,char * e,char * tag,uchar * o,int n)164 pserver(char *p, char *e, char *tag, uchar *o, int n)
165 {
166 p = seprint(p, e, "%s=(", tag);
167 while(n >= 4){
168 p = seprint(p, e, " %V", o);
169 n -= 4;
170 o += 4;
171 }
172 p = seprint(p, e, ")");
173 return p;
174 }
175
176 static char *dhcptype[256] =
177 {
178 [Discover] "Discover",
179 [Offer] "Offer",
180 [Request] "Request",
181 [Decline] "Decline",
182 [Ack] "Ack",
183 [Nak] "Nak",
184 [Release] "Release",
185 [Inform] "Inform",
186 };
187
188
189 static char*
ptype(char * p,char * e,uchar val)190 ptype(char *p, char *e, uchar val)
191 {
192 char *x;
193
194 x = dhcptype[val];
195 if(x != nil)
196 return seprint(p, e, "t=%s", x);
197 else
198 return seprint(p, e, "t=%d", val);
199 }
200
201 static int
p_seprint(Msg * m)202 p_seprint(Msg *m)
203 {
204 int i, n, code;
205 uchar *o, *ps;
206 char *p, *e;
207 char msg[64];
208
209 /* no next proto */
210 m->pr = nil;
211
212 p = m->p;
213 e = m->e;
214 ps = m->ps;
215
216 while(ps < m->pe){
217 code = *ps++;
218 if(code == 255)
219 break;
220 if(code == 0)
221 continue;
222
223 /* ignore anything that's too long */
224 n = *ps++;
225 o = ps;
226 ps += n;
227 if(ps > m->pe)
228 break;
229
230 switch(code){
231 case ODipaddr: /* requested ip address */
232 p = pserver(p, e, "ipaddr", o, n);
233 break;
234 case ODlease: /* requested lease time */
235 p = pint(p, e, "lease", o, n);
236 break;
237 case ODtype:
238 p = ptype(p, e, *o);
239 break;
240 case ODserverid:
241 p = pserver(p, e, "serverid", o, n);
242 break;
243 case ODmessage:
244 p = pstring(p, e, "message", o, n);
245 break;
246 case ODmaxmsg:
247 p = puint(p, e, "maxmsg", o, n);
248 break;
249 case ODclientid:
250 p = phex(p, e, "clientid", o, n);
251 break;
252 case ODparams:
253 p = seprint(p, e, " requested=(");
254 for(i = 0; i < n; i++){
255 if(i != 0)
256 p = seprint(p, e, " ");
257 p = seprint(p, e, "%ud", o[i]);
258 }
259 p = seprint(p, e, ")");
260 break;
261 case ODvendorclass:
262 p = pstring(p, e, "vendorclass", o, n);
263 break;
264 case OBmask:
265 p = pserver(p, e, "mask", o, n);
266 break;
267 case OBtimeoff:
268 p = pint(p, e, "timeoff", o, n);
269 break;
270 case OBrouter:
271 p = pserver(p, e, "router", o, n);
272 break;
273 case OBtimeserver:
274 p = pserver(p, e, "timesrv", o, n);
275 break;
276 case OBnameserver:
277 p = pserver(p, e, "namesrv", o, n);
278 break;
279 case OBdnserver:
280 p = pserver(p, e, "dnssrv", o, n);
281 break;
282 case OBlogserver:
283 p = pserver(p, e, "logsrv", o, n);
284 break;
285 case OBcookieserver:
286 p = pserver(p, e, "cookiesrv", o, n);
287 break;
288 case OBlprserver:
289 p = pserver(p, e, "lprsrv", o, n);
290 break;
291 case OBimpressserver:
292 p = pserver(p, e, "impresssrv", o, n);
293 break;
294 case OBrlserver:
295 p = pserver(p, e, "rlsrv", o, n);
296 break;
297 case OBhostname:
298 p = pstring(p, e, "hostname", o, n);
299 break;
300 case OBbflen:
301 break;
302 case OBdumpfile:
303 p = pstring(p, e, "dumpfile", o, n);
304 break;
305 case OBdomainname:
306 p = pstring(p, e, "domname", o, n);
307 break;
308 case OBswapserver:
309 p = pserver(p, e, "swapsrv", o, n);
310 break;
311 case OBrootpath:
312 p = pstring(p, e, "rootpath", o, n);
313 break;
314 case OBextpath:
315 p = pstring(p, e, "extpath", o, n);
316 break;
317 case OBipforward:
318 p = phex(p, e, "ipforward", o, n);
319 break;
320 case OBnonlocal:
321 p = phex(p, e, "nonlocal", o, n);
322 break;
323 case OBpolicyfilter:
324 p = phex(p, e, "policyfilter", o, n);
325 break;
326 case OBmaxdatagram:
327 p = phex(p, e, "maxdatagram", o, n);
328 break;
329 case OBttl:
330 p = puint(p, e, "ttl", o, n);
331 break;
332 case OBpathtimeout:
333 p = puint(p, e, "pathtimeout", o, n);
334 break;
335 case OBpathplateau:
336 p = phex(p, e, "pathplateau", o, n);
337 break;
338 case OBmtu:
339 p = puint(p, e, "mtu", o, n);
340 break;
341 case OBsubnetslocal:
342 p = pserver(p, e, "subnet", o, n);
343 break;
344 case OBbaddr:
345 p = pserver(p, e, "baddr", o, n);
346 break;
347 case OBdiscovermask:
348 p = pserver(p, e, "discovermsak", o, n);
349 break;
350 case OBsupplymask:
351 p = pserver(p, e, "rousupplymaskter", o, n);
352 break;
353 case OBdiscoverrouter:
354 p = pserver(p, e, "discoverrouter", o, n);
355 break;
356 case OBrsserver:
357 p = pserver(p, e, "rsrouter", o, n);
358 break;
359 case OBstaticroutes:
360 p = phex(p, e, "staticroutes", o, n);
361 break;
362 case OBtrailerencap:
363 p = phex(p, e, "trailerencap", o, n);
364 break;
365 case OBarptimeout:
366 p = puint(p, e, "arptimeout", o, n);
367 break;
368 case OBetherencap:
369 p = phex(p, e, "etherencap", o, n);
370 break;
371 case OBtcpttl:
372 p = puint(p, e, "tcpttl", o, n);
373 break;
374 case OBtcpka:
375 p = puint(p, e, "tcpka", o, n);
376 break;
377 case OBtcpkag:
378 p = phex(p, e, "tcpkag", o, n);
379 break;
380 case OBnisdomain:
381 p = pstring(p, e, "nisdomain", o, n);
382 break;
383 case OBniserver:
384 p = pserver(p, e, "nisrv", o, n);
385 break;
386 case OBntpserver:
387 p = pserver(p, e, "ntpsrv", o, n);
388 break;
389 case OBvendorinfo:
390 p = phex(p, e, "vendorinfo", o, n);
391 break;
392 case OBnetbiosns:
393 p = pserver(p, e, "biosns", o, n);
394 break;
395 case OBnetbiosdds:
396 p = phex(p, e, "biosdds", o, n);
397 break;
398 case OBnetbiostype:
399 p = phex(p, e, "biostype", o, n);
400 break;
401 case OBnetbiosscope:
402 p = phex(p, e, "biosscope", o, n);
403 break;
404 case OBxfontserver:
405 p = pserver(p, e, "fontsrv", o, n);
406 break;
407 case OBxdispmanager:
408 p = pserver(p, e, "xdispmgr", o, n);
409 break;
410 case OBnisplusdomain:
411 p = pstring(p, e, "nisplusdomain", o, n);
412 break;
413 case OBnisplusserver:
414 p = pserver(p, e, "nisplussrv", o, n);
415 break;
416 case OBhomeagent:
417 p = pserver(p, e, "homeagent", o, n);
418 break;
419 case OBsmtpserver:
420 p = pserver(p, e, "smtpsrv", o, n);
421 break;
422 case OBpop3server:
423 p = pserver(p, e, "pop3srv", o, n);
424 break;
425 case OBnntpserver:
426 p = pserver(p, e, "ntpsrv", o, n);
427 break;
428 case OBwwwserver:
429 p = pserver(p, e, "wwwsrv", o, n);
430 break;
431 case OBfingerserver:
432 p = pserver(p, e, "fingersrv", o, n);
433 break;
434 case OBircserver:
435 p = pserver(p, e, "ircsrv", o, n);
436 break;
437 case OBstserver:
438 p = pserver(p, e, "stsrv", o, n);
439 break;
440 case OBstdaserver:
441 p = pserver(p, e, "stdasrv", o, n);
442 break;
443 case OBend:
444 goto out;
445 default:
446 snprint(msg, sizeof msg, " T%ud", code);
447 p = phex(p, e, msg, o, n);
448 break;
449 }
450 if(*ps != OBend)
451 p = seprint(p, e, " ");
452 }
453 out:
454 m->p = p;
455 m->ps = ps;
456 return 0;
457 }
458
459 Proto dhcp =
460 {
461 "dhcp",
462 nil,
463 nil,
464 p_seprint,
465 nil,
466 nil,
467 nil,
468 defaultframer,
469 };
470