19a747e4fSDavid du Colombier #include <u.h> 29a747e4fSDavid du Colombier #include <libc.h> 39a747e4fSDavid du Colombier #include <ip.h> 49a747e4fSDavid du Colombier #include "dat.h" 59a747e4fSDavid du Colombier #include "protos.h" 69a747e4fSDavid du Colombier 79a747e4fSDavid du Colombier enum 89a747e4fSDavid du Colombier { 99a747e4fSDavid du Colombier OfferTimeout= 60, /* when an offer times out */ 109a747e4fSDavid du Colombier MaxLease= 60*60, /* longest lease for dynamic binding */ 119a747e4fSDavid du Colombier MinLease= 15*60, /* shortest lease for dynamic binding */ 129a747e4fSDavid du Colombier StaticLease= 30*60, /* lease for static binding */ 139a747e4fSDavid du Colombier 149a747e4fSDavid du Colombier IPUDPHDRSIZE= 28, /* size of an IP plus UDP header */ 159a747e4fSDavid du Colombier MINSUPPORTED= 576, /* biggest IP message the client must support */ 169a747e4fSDavid du Colombier 179a747e4fSDavid du Colombier /* lengths of some bootp fields */ 189a747e4fSDavid du Colombier Maxhwlen= 16, 199a747e4fSDavid du Colombier Maxfilelen= 128, 209a747e4fSDavid du Colombier Maxoptlen= 312-4, 219a747e4fSDavid du Colombier 229a747e4fSDavid du Colombier /* bootp types */ 239a747e4fSDavid du Colombier Bootrequest= 1, 249a747e4fSDavid du Colombier Bootreply= 2, 259a747e4fSDavid du Colombier 269a747e4fSDavid du Colombier /* bootp flags */ 279a747e4fSDavid du Colombier Fbroadcast= 1<<15, 289a747e4fSDavid du Colombier }; 299a747e4fSDavid du Colombier 309a747e4fSDavid du Colombier typedef struct Hdr Hdr; 319a747e4fSDavid du Colombier struct Hdr 329a747e4fSDavid du Colombier { 339a747e4fSDavid du Colombier uchar op; /* opcode */ 349a747e4fSDavid du Colombier uchar htype; /* hardware type */ 359a747e4fSDavid du Colombier uchar hlen; /* hardware address len */ 369a747e4fSDavid du Colombier uchar hops; /* hops */ 379a747e4fSDavid du Colombier uchar xid[4]; /* a random number */ 389a747e4fSDavid du Colombier uchar secs[2]; /* elapsed since client started booting */ 399a747e4fSDavid du Colombier uchar flags[2]; 409a747e4fSDavid du Colombier uchar ciaddr[IPv4addrlen]; /* client IP address (client tells server) */ 419a747e4fSDavid du Colombier uchar yiaddr[IPv4addrlen]; /* client IP address (server tells client) */ 429a747e4fSDavid du Colombier uchar siaddr[IPv4addrlen]; /* server IP address */ 439a747e4fSDavid du Colombier uchar giaddr[IPv4addrlen]; /* gateway IP address */ 449a747e4fSDavid du Colombier uchar chaddr[Maxhwlen]; /* client hardware address */ 459a747e4fSDavid du Colombier char sname[64]; /* server host name (optional) */ 469a747e4fSDavid du Colombier char file[Maxfilelen]; /* boot file name */ 479a747e4fSDavid du Colombier uchar optmagic[4]; 489a747e4fSDavid du Colombier uchar optdata[Maxoptlen]; 499a747e4fSDavid du Colombier }; 509a747e4fSDavid du Colombier 519a747e4fSDavid du Colombier enum 529a747e4fSDavid du Colombier { 539a747e4fSDavid du Colombier Oca, 549a747e4fSDavid du Colombier Osa, 559a747e4fSDavid du Colombier Ot, 569a747e4fSDavid du Colombier }; 579a747e4fSDavid du Colombier 589a747e4fSDavid du Colombier static Field p_fields[] = 599a747e4fSDavid du Colombier { 609a747e4fSDavid du Colombier {"ca", Fv4ip, Oca, "client IP addr", } , 619a747e4fSDavid du Colombier {"sa", Fv4ip, Osa, "server IP addr", } , 629a747e4fSDavid du Colombier {0} 639a747e4fSDavid du Colombier }; 649a747e4fSDavid du Colombier 659a747e4fSDavid du Colombier #define plan9opt ((ulong)(('p'<<24) | ('9'<<16) | (' '<<8) | ' ')) 669a747e4fSDavid du Colombier #define genericopt (0x63825363UL) 679a747e4fSDavid du Colombier 689a747e4fSDavid du Colombier static Mux p_mux[] = 699a747e4fSDavid du Colombier { 709a747e4fSDavid du Colombier {"dhcp", genericopt,}, 719a747e4fSDavid du Colombier {"plan9bootp", plan9opt,}, 729a747e4fSDavid du Colombier {"dump", 0,}, 739a747e4fSDavid du Colombier {0} 749a747e4fSDavid du Colombier }; 759a747e4fSDavid du Colombier 769a747e4fSDavid du Colombier static void 779a747e4fSDavid du Colombier p_compile(Filter *f) 789a747e4fSDavid du Colombier { 799a747e4fSDavid du Colombier Mux *m; 809a747e4fSDavid du Colombier 819a747e4fSDavid du Colombier if(f->op == '='){ 829a747e4fSDavid du Colombier compile_cmp(arp.name, f, p_fields); 839a747e4fSDavid du Colombier return; 849a747e4fSDavid du Colombier } 859a747e4fSDavid du Colombier for(m = p_mux; m->name != nil; m++) 869a747e4fSDavid du Colombier if(strcmp(f->s, m->name) == 0){ 879a747e4fSDavid du Colombier f->pr = m->pr; 889a747e4fSDavid du Colombier f->ulv = m->val; 899a747e4fSDavid du Colombier f->subop = Ot; 909a747e4fSDavid du Colombier return; 919a747e4fSDavid du Colombier } 929a747e4fSDavid du Colombier sysfatal("unknown bootp field: %s", f->s); 939a747e4fSDavid du Colombier } 949a747e4fSDavid du Colombier 959a747e4fSDavid du Colombier static int 969a747e4fSDavid du Colombier p_filter(Filter *f, Msg *m) 979a747e4fSDavid du Colombier { 989a747e4fSDavid du Colombier Hdr *h; 999a747e4fSDavid du Colombier 1009a747e4fSDavid du Colombier h = (Hdr*)m->ps; 1019a747e4fSDavid du Colombier 1029a747e4fSDavid du Colombier if(m->pe < (uchar*)h->sname) 1039a747e4fSDavid du Colombier return 0; 1049a747e4fSDavid du Colombier m->ps = h->optdata; 1059a747e4fSDavid du Colombier 1069a747e4fSDavid du Colombier switch(f->subop){ 1079a747e4fSDavid du Colombier case Oca: 1089a747e4fSDavid du Colombier return NetL(h->ciaddr) == f->ulv || NetL(h->yiaddr) == f->ulv; 1099a747e4fSDavid du Colombier case Osa: 1109a747e4fSDavid du Colombier return NetL(h->siaddr) == f->ulv; 1119a747e4fSDavid du Colombier case Ot: 1129a747e4fSDavid du Colombier return NetL(h->optmagic) == f->ulv; 1139a747e4fSDavid du Colombier } 1149a747e4fSDavid du Colombier return 0; 1159a747e4fSDavid du Colombier } 1169a747e4fSDavid du Colombier 1179a747e4fSDavid du Colombier static char* 1189a747e4fSDavid du Colombier op(int i) 1199a747e4fSDavid du Colombier { 1209a747e4fSDavid du Colombier static char x[20]; 1219a747e4fSDavid du Colombier 1229a747e4fSDavid du Colombier switch(i){ 1239a747e4fSDavid du Colombier case Bootrequest: 1249a747e4fSDavid du Colombier return "Req"; 1259a747e4fSDavid du Colombier case Bootreply: 1269a747e4fSDavid du Colombier return "Rep"; 1279a747e4fSDavid du Colombier default: 1289a747e4fSDavid du Colombier sprint(x, "%d", i); 1299a747e4fSDavid du Colombier return x; 1309a747e4fSDavid du Colombier } 1319a747e4fSDavid du Colombier } 1329a747e4fSDavid du Colombier 1339a747e4fSDavid du Colombier 1349a747e4fSDavid du Colombier static int 1359a747e4fSDavid du Colombier p_seprint(Msg *m) 1369a747e4fSDavid du Colombier { 1379a747e4fSDavid du Colombier Hdr *h; 1389a747e4fSDavid du Colombier ulong x; 1399a747e4fSDavid du Colombier 1409a747e4fSDavid du Colombier h = (Hdr*)m->ps; 1419a747e4fSDavid du Colombier 1429a747e4fSDavid du Colombier if(m->pe < (uchar*)h->sname) 1439a747e4fSDavid du Colombier return -1; 1449a747e4fSDavid du Colombier 1459a747e4fSDavid du Colombier /* point past data */ 1469a747e4fSDavid du Colombier m->ps = h->optdata; 1479a747e4fSDavid du Colombier 1489a747e4fSDavid du Colombier /* next protocol */ 1499a747e4fSDavid du Colombier m->pr = nil; 1509a747e4fSDavid du Colombier if(m->pe >= (uchar*)h->optdata){ 1519a747e4fSDavid du Colombier x = NetL(h->optmagic); 1529a747e4fSDavid du Colombier demux(p_mux, x, x, m, &dump); 1539a747e4fSDavid du Colombier } 1549a747e4fSDavid du Colombier 1559a747e4fSDavid du Colombier 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", 1569a747e4fSDavid du Colombier op(h->op), h->htype, h->hlen, h->hops, 1579a747e4fSDavid du Colombier NetL(h->xid), NetS(h->secs), NetS(h->flags), 1589a747e4fSDavid du Colombier h->ciaddr, h->yiaddr, h->siaddr, h->giaddr, h->chaddr, 1599a747e4fSDavid du Colombier (ulong)NetL(h->optmagic)); 1609a747e4fSDavid du Colombier if(m->pe > (uchar*)h->sname && *h->sname) 1619a747e4fSDavid du Colombier m->p = seprint(m->p, m->e, " snam=%s", h->sname); 1629a747e4fSDavid du Colombier if(m->pe > (uchar*)h->file && *h->file) 1639a747e4fSDavid du Colombier m->p = seprint(m->p, m->e, " file=%s", h->file); 1649a747e4fSDavid du Colombier return 0; 1659a747e4fSDavid du Colombier } 1669a747e4fSDavid du Colombier 1679a747e4fSDavid du Colombier Proto bootp = 1689a747e4fSDavid du Colombier { 1699a747e4fSDavid du Colombier "bootp", 1709a747e4fSDavid du Colombier p_compile, 1719a747e4fSDavid du Colombier p_filter, 1729a747e4fSDavid du Colombier p_seprint, 1739a747e4fSDavid du Colombier p_mux, 174*ed397113SDavid du Colombier "%#.8lux", 1759a747e4fSDavid du Colombier p_fields, 1763ff48bf5SDavid du Colombier defaultframer, 1779a747e4fSDavid du Colombier }; 178