#include #include #include #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 */ OP9fsv4= 128, /* plan9 file servers */ OP9authv4= 129, /* plan9 auth servers */ }; /* * 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", nil, nil, p_seprint, nil, nil, nil, defaultframer, };