Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#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 */
        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,
};