plan9port

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

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 };