aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/ip/snoopy/bootp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/ip/snoopy/bootp.c')
-rwxr-xr-xsrc/cmd/ip/snoopy/bootp.c176
1 files changed, 176 insertions, 0 deletions
diff --git a/src/cmd/ip/snoopy/bootp.c b/src/cmd/ip/snoopy/bootp.c
new file mode 100755
index 00000000..1adfdad1
--- /dev/null
+++ b/src/cmd/ip/snoopy/bootp.c
@@ -0,0 +1,176 @@
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+#include "dat.h"
+#include "protos.h"
+
+enum
+{
+ OfferTimeout= 60, /* when an offer times out */
+ MaxLease= 60*60, /* longest lease for dynamic binding */
+ MinLease= 15*60, /* shortest lease for dynamic binding */
+ StaticLease= 30*60, /* lease for static binding */
+
+ IPUDPHDRSIZE= 28, /* size of an IP plus UDP header */
+ MINSUPPORTED= 576, /* biggest IP message the client must support */
+
+ /* lengths of some bootp fields */
+ Maxhwlen= 16,
+ Maxfilelen= 128,
+ Maxoptlen= 312-4,
+
+ /* bootp types */
+ Bootrequest= 1,
+ Bootreply= 2,
+
+ /* bootp flags */
+ Fbroadcast= 1<<15,
+};
+
+typedef struct Hdr Hdr;
+struct Hdr
+{
+ uchar op; /* opcode */
+ uchar htype; /* hardware type */
+ uchar hlen; /* hardware address len */
+ uchar hops; /* hops */
+ uchar xid[4]; /* a random number */
+ uchar secs[2]; /* elapsed since client started booting */
+ uchar flags[2];
+ uchar ciaddr[IPv4addrlen]; /* client IP address (client tells server) */
+ uchar yiaddr[IPv4addrlen]; /* client IP address (server tells client) */
+ uchar siaddr[IPv4addrlen]; /* server IP address */
+ uchar giaddr[IPv4addrlen]; /* gateway IP address */
+ uchar chaddr[Maxhwlen]; /* client hardware address */
+ char sname[64]; /* server host name (optional) */
+ char file[Maxfilelen]; /* boot file name */
+ uchar optmagic[4];
+ uchar optdata[Maxoptlen];
+};
+
+enum
+{
+ Oca,
+ Osa,
+ Ot,
+};
+
+static Field p_fields[] =
+{
+ {"ca", Fv4ip, Oca, "client IP addr", } ,
+ {"sa", Fv4ip, Osa, "server IP addr", } ,
+ {0}
+};
+
+#define plan9opt ((ulong)(('p'<<24) | ('9'<<16) | (' '<<8) | ' '))
+#define genericopt (0x63825363UL)
+
+static Mux p_mux[] =
+{
+ {"dhcp", genericopt,},
+ {"plan9bootp", plan9opt,},
+ {"dump", 0,},
+ {0}
+};
+
+static void
+p_compile(Filter *f)
+{
+ Mux *m;
+
+ if(f->op == '='){
+ compile_cmp(arp.name, f, p_fields);
+ return;
+ }
+ for(m = p_mux; m->name != nil; m++)
+ if(strcmp(f->s, m->name) == 0){
+ f->pr = m->pr;
+ f->ulv = m->val;
+ f->subop = Ot;
+ return;
+ }
+ sysfatal("unknown bootp field: %s", f->s);
+}
+
+static int
+p_filter(Filter *f, Msg *m)
+{
+ Hdr *h;
+
+ h = (Hdr*)m->ps;
+
+ if(m->pe < (uchar*)h->sname)
+ return 0;
+ m->ps = h->optdata;
+
+ switch(f->subop){
+ case Oca:
+ return NetL(h->ciaddr) == f->ulv || NetL(h->yiaddr) == f->ulv;
+ case Osa:
+ return NetL(h->siaddr) == f->ulv;
+ case Ot:
+ return NetL(h->optmagic) == f->ulv;
+ }
+ return 0;
+}
+
+static char*
+op(int i)
+{
+ static char x[20];
+
+ switch(i){
+ case Bootrequest:
+ return "Req";
+ case Bootreply:
+ return "Rep";
+ default:
+ sprint(x, "%d", i);
+ return x;
+ }
+}
+
+
+static int
+p_seprint(Msg *m)
+{
+ Hdr *h;
+ ulong x;
+
+ h = (Hdr*)m->ps;
+
+ if(m->pe < (uchar*)h->sname)
+ return -1;
+
+ /* point past data */
+ m->ps = h->optdata;
+
+ /* next protocol */
+ m->pr = nil;
+ if(m->pe >= (uchar*)h->optdata){
+ x = NetL(h->optmagic);
+ demux(p_mux, x, x, m, &dump);
+ }
+
+ m->p = seprint(m->p, m->e, "t=%s ht=%d hl=%d hp=%d xid=%ux sec=%d fl=%4.4ux ca=%V ya=%V sa=%V ga=%V cha=%E magic=%lux",
+ op(h->op), h->htype, h->hlen, h->hops,
+ NetL(h->xid), NetS(h->secs), NetS(h->flags),
+ h->ciaddr, h->yiaddr, h->siaddr, h->giaddr, h->chaddr,
+ (ulong)NetL(h->optmagic));
+ if(m->pe > (uchar*)h->sname && *h->sname)
+ m->p = seprint(m->p, m->e, " snam=%s", h->sname);
+ if(m->pe > (uchar*)h->file && *h->file)
+ m->p = seprint(m->p, m->e, " file=%s", h->file);
+ return 0;
+}
+
+Proto bootp =
+{
+ "bootp",
+ p_compile,
+ p_filter,
+ p_seprint,
+ p_mux,
+ p_fields,
+ defaultframer,
+};