dhcp.c (9045B)
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 OP9fs= 128, /* plan9 file servers */ 103 OP9auth= 129, /* plan9 auth servers */ 104 }; 105 106 static void 107 p_compile(Filter *f) 108 { 109 sysfatal("unknown dhcp field: %s", f->s); 110 } 111 112 /* 113 * convert a byte array to hex 114 */ 115 static char 116 hex(int x) 117 { 118 if(x < 10) 119 return x + '0'; 120 return x - 10 + 'a'; 121 } 122 static char* 123 phex(char *p, char *e, char *tag, uchar *o, int n) 124 { 125 p = seprint(p, e, "%s=", tag); 126 127 for(; p+2 < e && n > 0; n--){ 128 *p++ = hex(*o>>4); 129 *p++ = hex(*o & 0xf); 130 o++; 131 } 132 return p; 133 } 134 135 static char* 136 pstring(char *p, char *e, char *tag, uchar *o, int n) 137 { 138 char msg[256]; 139 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); 145 } 146 147 static char* 148 pint(char *p, char *e, char *tag, uchar *o, int n) 149 { 150 int x; 151 152 x = *(char*)o++; 153 for(; n > 1; n--) 154 x = (x<<8)|*o++; 155 return seprint(p, e, "%s=%d", tag, x); 156 } 157 158 static char* 159 puint(char *p, char *e, char *tag, uchar *o, int n) 160 { 161 uint x; 162 163 x = *o++; 164 for(; n > 1; n--) 165 x = (x<<8)|*o++; 166 return seprint(p, e, "%s=%ud", tag, x); 167 } 168 169 static char* 170 pserver(char *p, char *e, char *tag, uchar *o, int n) 171 { 172 p = seprint(p, e, "%s=(", tag); 173 while(n >= 4){ 174 p = seprint(p, e, " %V", o); 175 n -= 4; 176 o += 4; 177 } 178 p = seprint(p, e, ")"); 179 return p; 180 } 181 182 static char *dhcptype[256] = 183 { 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 }; 193 194 195 static char* 196 ptype(char *p, char *e, uchar val) 197 { 198 char *x; 199 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); 205 } 206 207 static int 208 p_seprint(Msg *m) 209 { 210 int i, n, code; 211 uchar *o, *ps; 212 char *p, *e; 213 char msg[64]; 214 215 /* no next proto */ 216 m->pr = nil; 217 218 p = m->p; 219 e = m->e; 220 ps = m->ps; 221 222 while(ps < m->pe){ 223 code = *ps++; 224 if(code == 255) 225 break; 226 if(code == 0) 227 continue; 228 229 /* ignore anything that's too long */ 230 n = *ps++; 231 o = ps; 232 ps += n; 233 if(ps > m->pe) 234 break; 235 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]); 264 } 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; 455 } 456 if(*ps != OBend) 457 p = seprint(p, e, " "); 458 } 459 out: 460 m->p = p; 461 m->ps = ps; 462 return 0; 463 } 464 465 Proto dhcp = 466 { 467 "dhcp", 468 p_compile, 469 nil, 470 p_seprint, 471 nil, 472 nil, 473 nil, 474 defaultframer 475 };