484 lines
8.9 KiB
C
484 lines
8.9 KiB
C
|
|
#include <u.h>
|
||
|
|
#include <libc.h>
|
||
|
|
#include <ip.h>
|
||
|
|
#include "dat.h"
|
||
|
|
#include "protos.h"
|
||
|
|
|
||
|
|
enum
|
||
|
|
{
|
||
|
|
Maxoptlen= 312-4,
|
||
|
|
|
||
|
|
/* dhcp types */
|
||
|
|
Discover= 1,
|
||
|
|
Offer= 2,
|
||
|
|
Request= 3,
|
||
|
|
Decline= 4,
|
||
|
|
Ack= 5,
|
||
|
|
Nak= 6,
|
||
|
|
Release= 7,
|
||
|
|
Inform= 8,
|
||
|
|
|
||
|
|
/* bootp option types */
|
||
|
|
OBend= 255,
|
||
|
|
OBpad= 0,
|
||
|
|
OBmask= 1,
|
||
|
|
OBtimeoff= 2,
|
||
|
|
OBrouter= 3,
|
||
|
|
OBtimeserver= 4,
|
||
|
|
OBnameserver= 5,
|
||
|
|
OBdnserver= 6,
|
||
|
|
OBlogserver= 7,
|
||
|
|
OBcookieserver= 8,
|
||
|
|
OBlprserver= 9,
|
||
|
|
OBimpressserver= 10,
|
||
|
|
OBrlserver= 11,
|
||
|
|
OBhostname= 12, /* 0xc0 */
|
||
|
|
OBbflen= 13,
|
||
|
|
OBdumpfile= 14,
|
||
|
|
OBdomainname= 15,
|
||
|
|
OBswapserver= 16, /* 0x10 */
|
||
|
|
OBrootpath= 17,
|
||
|
|
OBextpath= 18,
|
||
|
|
OBipforward= 19,
|
||
|
|
OBnonlocal= 20,
|
||
|
|
OBpolicyfilter= 21,
|
||
|
|
OBmaxdatagram= 22,
|
||
|
|
OBttl= 23,
|
||
|
|
OBpathtimeout= 24,
|
||
|
|
OBpathplateau= 25,
|
||
|
|
OBmtu= 26,
|
||
|
|
OBsubnetslocal= 27,
|
||
|
|
OBbaddr= 28,
|
||
|
|
OBdiscovermask= 29,
|
||
|
|
OBsupplymask= 30,
|
||
|
|
OBdiscoverrouter= 31,
|
||
|
|
OBrsserver= 32, /* 0x20 */
|
||
|
|
OBstaticroutes= 33,
|
||
|
|
OBtrailerencap= 34,
|
||
|
|
OBarptimeout= 35,
|
||
|
|
OBetherencap= 36,
|
||
|
|
OBtcpttl= 37,
|
||
|
|
OBtcpka= 38,
|
||
|
|
OBtcpkag= 39,
|
||
|
|
OBnisdomain= 40,
|
||
|
|
OBniserver= 41,
|
||
|
|
OBntpserver= 42,
|
||
|
|
OBvendorinfo= 43, /* 0x2b */
|
||
|
|
OBnetbiosns= 44,
|
||
|
|
OBnetbiosdds= 45,
|
||
|
|
OBnetbiostype= 46,
|
||
|
|
OBnetbiosscope= 47,
|
||
|
|
OBxfontserver= 48, /* 0x30 */
|
||
|
|
OBxdispmanager= 49,
|
||
|
|
OBnisplusdomain= 64, /* 0x40 */
|
||
|
|
OBnisplusserver= 65,
|
||
|
|
OBhomeagent= 68,
|
||
|
|
OBsmtpserver= 69,
|
||
|
|
OBpop3server= 70,
|
||
|
|
OBnntpserver= 71,
|
||
|
|
OBwwwserver= 72,
|
||
|
|
OBfingerserver= 73,
|
||
|
|
OBircserver= 74,
|
||
|
|
OBstserver= 75,
|
||
|
|
OBstdaserver= 76,
|
||
|
|
|
||
|
|
/* dhcp options */
|
||
|
|
ODipaddr= 50, /* 0x32 */
|
||
|
|
ODlease= 51,
|
||
|
|
ODoverload= 52,
|
||
|
|
ODtype= 53, /* 0x35 */
|
||
|
|
ODserverid= 54, /* 0x36 */
|
||
|
|
ODparams= 55, /* 0x37 */
|
||
|
|
ODmessage= 56,
|
||
|
|
ODmaxmsg= 57,
|
||
|
|
ODrenewaltime= 58,
|
||
|
|
ODrebindingtime= 59,
|
||
|
|
ODvendorclass= 60,
|
||
|
|
ODclientid= 61, /* 0x3d */
|
||
|
|
ODtftpserver= 66,
|
||
|
|
ODbootfile= 67,
|
||
|
|
|
||
|
|
/* plan9 vendor info options */
|
||
|
|
OP9fs= 128, // plan9 file servers
|
||
|
|
OP9auth= 129, // plan9 auth servers
|
||
|
|
};
|
||
|
|
|
||
|
|
static void
|
||
|
|
p_compile(Filter *f)
|
||
|
|
{
|
||
|
|
sysfatal("unknown bootp field: %s", f->s);
|
||
|
|
}
|
||
|
|
|
||
|
|
static int
|
||
|
|
p_filter(Filter *f, Msg *m)
|
||
|
|
{
|
||
|
|
USED(f);
|
||
|
|
USED(m);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
* convert a byte array to hex
|
||
|
|
*/
|
||
|
|
static char
|
||
|
|
hex(int x)
|
||
|
|
{
|
||
|
|
if(x < 10)
|
||
|
|
return x + '0';
|
||
|
|
return x - 10 + 'a';
|
||
|
|
}
|
||
|
|
static char*
|
||
|
|
phex(char *p, char *e, char *tag, uchar *o, int n)
|
||
|
|
{
|
||
|
|
p = seprint(p, e, "%s=", tag);
|
||
|
|
|
||
|
|
for(; p+2 < e && n > 0; n--){
|
||
|
|
*p++ = hex(*o>>4);
|
||
|
|
*p++ = hex(*o & 0xf);
|
||
|
|
o++;
|
||
|
|
}
|
||
|
|
return p;
|
||
|
|
}
|
||
|
|
|
||
|
|
static char*
|
||
|
|
pstring(char *p, char *e, char *tag, uchar *o, int n)
|
||
|
|
{
|
||
|
|
char msg[256];
|
||
|
|
|
||
|
|
if(n > sizeof msg - 1)
|
||
|
|
n = sizeof msg - 1;
|
||
|
|
memmove(msg, o, n);
|
||
|
|
msg[n] = 0;
|
||
|
|
return seprint(p, e, "%s=%s", tag, msg);
|
||
|
|
}
|
||
|
|
|
||
|
|
static char*
|
||
|
|
pint(char *p, char *e, char *tag, uchar *o, int n)
|
||
|
|
{
|
||
|
|
int x;
|
||
|
|
|
||
|
|
x = *(char*)o++;
|
||
|
|
for(; n > 1; n--)
|
||
|
|
x = (x<<8)|*o++;
|
||
|
|
return seprint(p, e, "%s=%d", tag, x);
|
||
|
|
}
|
||
|
|
|
||
|
|
static char*
|
||
|
|
puint(char *p, char *e, char *tag, uchar *o, int n)
|
||
|
|
{
|
||
|
|
uint x;
|
||
|
|
|
||
|
|
x = *o++;
|
||
|
|
for(; n > 1; n--)
|
||
|
|
x = (x<<8)|*o++;
|
||
|
|
return seprint(p, e, "%s=%ud", tag, x);
|
||
|
|
}
|
||
|
|
|
||
|
|
static char*
|
||
|
|
pserver(char *p, char *e, char *tag, uchar *o, int n)
|
||
|
|
{
|
||
|
|
p = seprint(p, e, "%s=(", tag);
|
||
|
|
while(n >= 4){
|
||
|
|
p = seprint(p, e, " %V", o);
|
||
|
|
n -= 4;
|
||
|
|
o += 4;
|
||
|
|
}
|
||
|
|
p = seprint(p, e, ")");
|
||
|
|
return p;
|
||
|
|
}
|
||
|
|
|
||
|
|
static char *dhcptype[256] =
|
||
|
|
{
|
||
|
|
[Discover] "Discover",
|
||
|
|
[Offer] "Offer",
|
||
|
|
[Request] "Request",
|
||
|
|
[Decline] "Decline",
|
||
|
|
[Ack] "Ack",
|
||
|
|
[Nak] "Nak",
|
||
|
|
[Release] "Release",
|
||
|
|
[Inform] "Inform",
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
static char*
|
||
|
|
ptype(char *p, char *e, uchar val)
|
||
|
|
{
|
||
|
|
char *x;
|
||
|
|
|
||
|
|
x = dhcptype[val];
|
||
|
|
if(x != nil)
|
||
|
|
return seprint(p, e, "t=%s", x);
|
||
|
|
else
|
||
|
|
return seprint(p, e, "t=%d", val);
|
||
|
|
}
|
||
|
|
|
||
|
|
static int
|
||
|
|
p_seprint(Msg *m)
|
||
|
|
{
|
||
|
|
int i, n, code;
|
||
|
|
uchar *o, *ps;
|
||
|
|
char *p, *e;
|
||
|
|
char msg[64];
|
||
|
|
|
||
|
|
/* no next proto */
|
||
|
|
m->pr = nil;
|
||
|
|
|
||
|
|
p = m->p;
|
||
|
|
e = m->e;
|
||
|
|
ps = m->ps;
|
||
|
|
|
||
|
|
while(ps < m->pe){
|
||
|
|
code = *ps++;
|
||
|
|
if(code == 255)
|
||
|
|
break;
|
||
|
|
if(code == 0)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
/* ignore anything that's too long */
|
||
|
|
n = *ps++;
|
||
|
|
o = ps;
|
||
|
|
ps += n;
|
||
|
|
if(ps > m->pe)
|
||
|
|
break;
|
||
|
|
|
||
|
|
switch(code){
|
||
|
|
case ODipaddr: /* requested ip address */
|
||
|
|
p = pserver(p, e, "ipaddr", o, n);
|
||
|
|
break;
|
||
|
|
case ODlease: /* requested lease time */
|
||
|
|
p = pint(p, e, "lease", o, n);
|
||
|
|
break;
|
||
|
|
case ODtype:
|
||
|
|
p = ptype(p, e, *o);
|
||
|
|
break;
|
||
|
|
case ODserverid:
|
||
|
|
p = pserver(p, e, "serverid", o, n);
|
||
|
|
break;
|
||
|
|
case ODmessage:
|
||
|
|
p = pstring(p, e, "message", o, n);
|
||
|
|
break;
|
||
|
|
case ODmaxmsg:
|
||
|
|
p = puint(p, e, "maxmsg", o, n);
|
||
|
|
break;
|
||
|
|
case ODclientid:
|
||
|
|
p = phex(p, e, "clientid", o, n);
|
||
|
|
break;
|
||
|
|
case ODparams:
|
||
|
|
p = seprint(p, e, " requested=(");
|
||
|
|
for(i = 0; i < n; i++){
|
||
|
|
if(i != 0)
|
||
|
|
p = seprint(p, e, " ");
|
||
|
|
p = seprint(p, e, "%ud", o[i]);
|
||
|
|
}
|
||
|
|
p = seprint(p, e, ")");
|
||
|
|
break;
|
||
|
|
case ODvendorclass:
|
||
|
|
p = pstring(p, e, "vendorclass", o, n);
|
||
|
|
break;
|
||
|
|
case OBmask:
|
||
|
|
p = pserver(p, e, "mask", o, n);
|
||
|
|
break;
|
||
|
|
case OBtimeoff:
|
||
|
|
p = pint(p, e, "timeoff", o, n);
|
||
|
|
break;
|
||
|
|
case OBrouter:
|
||
|
|
p = pserver(p, e, "router", o, n);
|
||
|
|
break;
|
||
|
|
case OBtimeserver:
|
||
|
|
p = pserver(p, e, "timesrv", o, n);
|
||
|
|
break;
|
||
|
|
case OBnameserver:
|
||
|
|
p = pserver(p, e, "namesrv", o, n);
|
||
|
|
break;
|
||
|
|
case OBdnserver:
|
||
|
|
p = pserver(p, e, "dnssrv", o, n);
|
||
|
|
break;
|
||
|
|
case OBlogserver:
|
||
|
|
p = pserver(p, e, "logsrv", o, n);
|
||
|
|
break;
|
||
|
|
case OBcookieserver:
|
||
|
|
p = pserver(p, e, "cookiesrv", o, n);
|
||
|
|
break;
|
||
|
|
case OBlprserver:
|
||
|
|
p = pserver(p, e, "lprsrv", o, n);
|
||
|
|
break;
|
||
|
|
case OBimpressserver:
|
||
|
|
p = pserver(p, e, "impresssrv", o, n);
|
||
|
|
break;
|
||
|
|
case OBrlserver:
|
||
|
|
p = pserver(p, e, "rlsrv", o, n);
|
||
|
|
break;
|
||
|
|
case OBhostname:
|
||
|
|
p = pstring(p, e, "hostname", o, n);
|
||
|
|
break;
|
||
|
|
case OBbflen:
|
||
|
|
break;
|
||
|
|
case OBdumpfile:
|
||
|
|
p = pstring(p, e, "dumpfile", o, n);
|
||
|
|
break;
|
||
|
|
case OBdomainname:
|
||
|
|
p = pstring(p, e, "domname", o, n);
|
||
|
|
break;
|
||
|
|
case OBswapserver:
|
||
|
|
p = pserver(p, e, "swapsrv", o, n);
|
||
|
|
break;
|
||
|
|
case OBrootpath:
|
||
|
|
p = pstring(p, e, "rootpath", o, n);
|
||
|
|
break;
|
||
|
|
case OBextpath:
|
||
|
|
p = pstring(p, e, "extpath", o, n);
|
||
|
|
break;
|
||
|
|
case OBipforward:
|
||
|
|
p = phex(p, e, "ipforward", o, n);
|
||
|
|
break;
|
||
|
|
case OBnonlocal:
|
||
|
|
p = phex(p, e, "nonlocal", o, n);
|
||
|
|
break;
|
||
|
|
case OBpolicyfilter:
|
||
|
|
p = phex(p, e, "policyfilter", o, n);
|
||
|
|
break;
|
||
|
|
case OBmaxdatagram:
|
||
|
|
p = phex(p, e, "maxdatagram", o, n);
|
||
|
|
break;
|
||
|
|
case OBttl:
|
||
|
|
p = puint(p, e, "ttl", o, n);
|
||
|
|
break;
|
||
|
|
case OBpathtimeout:
|
||
|
|
p = puint(p, e, "pathtimeout", o, n);
|
||
|
|
break;
|
||
|
|
case OBpathplateau:
|
||
|
|
p = phex(p, e, "pathplateau", o, n);
|
||
|
|
break;
|
||
|
|
case OBmtu:
|
||
|
|
p = puint(p, e, "mtu", o, n);
|
||
|
|
break;
|
||
|
|
case OBsubnetslocal:
|
||
|
|
p = pserver(p, e, "subnet", o, n);
|
||
|
|
break;
|
||
|
|
case OBbaddr:
|
||
|
|
p = pserver(p, e, "baddr", o, n);
|
||
|
|
break;
|
||
|
|
case OBdiscovermask:
|
||
|
|
p = pserver(p, e, "discovermsak", o, n);
|
||
|
|
break;
|
||
|
|
case OBsupplymask:
|
||
|
|
p = pserver(p, e, "rousupplymaskter", o, n);
|
||
|
|
break;
|
||
|
|
case OBdiscoverrouter:
|
||
|
|
p = pserver(p, e, "discoverrouter", o, n);
|
||
|
|
break;
|
||
|
|
case OBrsserver:
|
||
|
|
p = pserver(p, e, "rsrouter", o, n);
|
||
|
|
break;
|
||
|
|
case OBstaticroutes:
|
||
|
|
p = phex(p, e, "staticroutes", o, n);
|
||
|
|
break;
|
||
|
|
case OBtrailerencap:
|
||
|
|
p = phex(p, e, "trailerencap", o, n);
|
||
|
|
break;
|
||
|
|
case OBarptimeout:
|
||
|
|
p = puint(p, e, "arptimeout", o, n);
|
||
|
|
break;
|
||
|
|
case OBetherencap:
|
||
|
|
p = phex(p, e, "etherencap", o, n);
|
||
|
|
break;
|
||
|
|
case OBtcpttl:
|
||
|
|
p = puint(p, e, "tcpttl", o, n);
|
||
|
|
break;
|
||
|
|
case OBtcpka:
|
||
|
|
p = puint(p, e, "tcpka", o, n);
|
||
|
|
break;
|
||
|
|
case OBtcpkag:
|
||
|
|
p = phex(p, e, "tcpkag", o, n);
|
||
|
|
break;
|
||
|
|
case OBnisdomain:
|
||
|
|
p = pstring(p, e, "nisdomain", o, n);
|
||
|
|
break;
|
||
|
|
case OBniserver:
|
||
|
|
p = pserver(p, e, "nisrv", o, n);
|
||
|
|
break;
|
||
|
|
case OBntpserver:
|
||
|
|
p = pserver(p, e, "ntpsrv", o, n);
|
||
|
|
break;
|
||
|
|
case OBvendorinfo:
|
||
|
|
p = phex(p, e, "vendorinfo", o, n);
|
||
|
|
break;
|
||
|
|
case OBnetbiosns:
|
||
|
|
p = pserver(p, e, "biosns", o, n);
|
||
|
|
break;
|
||
|
|
case OBnetbiosdds:
|
||
|
|
p = phex(p, e, "biosdds", o, n);
|
||
|
|
break;
|
||
|
|
case OBnetbiostype:
|
||
|
|
p = phex(p, e, "biostype", o, n);
|
||
|
|
break;
|
||
|
|
case OBnetbiosscope:
|
||
|
|
p = phex(p, e, "biosscope", o, n);
|
||
|
|
break;
|
||
|
|
case OBxfontserver:
|
||
|
|
p = pserver(p, e, "fontsrv", o, n);
|
||
|
|
break;
|
||
|
|
case OBxdispmanager:
|
||
|
|
p = pserver(p, e, "xdispmgr", o, n);
|
||
|
|
break;
|
||
|
|
case OBnisplusdomain:
|
||
|
|
p = pstring(p, e, "nisplusdomain", o, n);
|
||
|
|
break;
|
||
|
|
case OBnisplusserver:
|
||
|
|
p = pserver(p, e, "nisplussrv", o, n);
|
||
|
|
break;
|
||
|
|
case OBhomeagent:
|
||
|
|
p = pserver(p, e, "homeagent", o, n);
|
||
|
|
break;
|
||
|
|
case OBsmtpserver:
|
||
|
|
p = pserver(p, e, "smtpsrv", o, n);
|
||
|
|
break;
|
||
|
|
case OBpop3server:
|
||
|
|
p = pserver(p, e, "pop3srv", o, n);
|
||
|
|
break;
|
||
|
|
case OBnntpserver:
|
||
|
|
p = pserver(p, e, "ntpsrv", o, n);
|
||
|
|
break;
|
||
|
|
case OBwwwserver:
|
||
|
|
p = pserver(p, e, "wwwsrv", o, n);
|
||
|
|
break;
|
||
|
|
case OBfingerserver:
|
||
|
|
p = pserver(p, e, "fingersrv", o, n);
|
||
|
|
break;
|
||
|
|
case OBircserver:
|
||
|
|
p = pserver(p, e, "ircsrv", o, n);
|
||
|
|
break;
|
||
|
|
case OBstserver:
|
||
|
|
p = pserver(p, e, "stsrv", o, n);
|
||
|
|
break;
|
||
|
|
case OBstdaserver:
|
||
|
|
p = pserver(p, e, "stdasrv", o, n);
|
||
|
|
break;
|
||
|
|
case OBend:
|
||
|
|
goto out;
|
||
|
|
default:
|
||
|
|
snprint(msg, sizeof msg, " T%ud", code);
|
||
|
|
p = phex(p, e, msg, o, n);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if(*ps != OBend)
|
||
|
|
p = seprint(p, e, " ");
|
||
|
|
}
|
||
|
|
out:
|
||
|
|
m->p = p;
|
||
|
|
m->ps = ps;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
Proto dhcp =
|
||
|
|
{
|
||
|
|
"dhcp",
|
||
|
|
p_compile,
|
||
|
|
p_filter,
|
||
|
|
p_seprint,
|
||
|
|
nil,
|
||
|
|
nil,
|
||
|
|
defaultframer,
|
||
|
|
};
|
||
|
|
|