static long ipwrite(Chan* ch, void *v, long n, vlong off) { Conv *c; Proto *x; char *p; Cmdbuf *cb; uchar ia[IPaddrlen], ma[IPaddrlen]; Fs *f; char *a; ulong offset = off; a = v; f = ipfs[ch->dev]; switch(TYPE(ch->qid)){ default: error(Eperm); case Qdata: x = f->p[PROTO(ch->qid)]; c = x->conv[CONV(ch->qid)]; if(c->wq == nil) error(Eperm); qwrite(c->wq, a, n); break; case Qarp: return arpwrite(f, a, n); case Qiproute: return routewrite(f, ch, a, n); case Qlog: netlogctl(f, a, n); return n; case Qndb: return ndbwrite(f, a, offset, n); break; case Qctl: x = f->p[PROTO(ch->qid)]; c = x->conv[CONV(ch->qid)]; cb = parsecmd(a, n); qlock(c); if(waserror()) { qunlock(c); free(cb); nexterror(); } if(cb->nf < 1) error("short control request"); if(strcmp(cb->f[0], "connect") == 0) connectctlmsg(x, c, cb); else if(strcmp(cb->f[0], "announce") == 0) announcectlmsg(x, c, cb); else if(strcmp(cb->f[0], "bind") == 0) bindctlmsg(x, c, cb); else if(strcmp(cb->f[0], "ttl") == 0) ttlctlmsg(c, cb); else if(strcmp(cb->f[0], "tos") == 0) tosctlmsg(c, cb); else if(strcmp(cb->f[0], "ignoreadvice") == 0) c->ignoreadvice = 1; else if(strcmp(cb->f[0], "addmulti") == 0){ if(cb->nf < 2) error("addmulti needs interface address"); if(cb->nf == 2){ if(!ipismulticast(c->raddr)) error("addmulti for a non multicast address"); if (parseip(ia, cb->f[1]) == -1) error(Ebadip); ipifcaddmulti(c, c->raddr, ia); } else { if (parseip(ia, cb->f[1]) == -1 || parseip(ma, cb->f[2]) == -1) error(Ebadip); if(!ipismulticast(ma)) error("addmulti for a non multicast address"); ipifcaddmulti(c, ma, ia); } } else if(strcmp(cb->f[0], "remmulti") == 0){ if(cb->nf < 2) error("remmulti needs interface address"); if(!ipismulticast(c->raddr)) error("remmulti for a non multicast address"); if (parseip(ia, cb->f[1]) == -1) error(Ebadip); ipifcremmulti(c, c->raddr, ia); } else if(strcmp(cb->f[0], "maxfragsize") == 0){ if(cb->nf < 2) error("maxfragsize needs size"); c->maxfragsize = (int)strtol(cb->f[1], nil, 0); } else if(x->ctl != nil) { p = x->ctl(c, cb->f, cb->nf); if(p != nil) error(p); } else error("unknown control request"); qunlock(c); free(cb); poperror(); } return n; }
static char* rbootp(Ipifc *ifc) { int cfd, dfd, tries, n; char ia[5+3*16], im[16], *av[3]; uchar nipaddr[4], ngwip[4], nipmask[4]; char dir[Maxpath]; static uchar vend_rfc1048[] = { 99, 130, 83, 99 }; uchar *vend; /* * broadcast bootp's till we get a reply, * or fixed number of tries */ if(debug) print("dhcp: bootp() called\n"); tries = 0; av[1] = "0.0.0.0"; av[2] = "0.0.0.0"; ipifcadd(ifc, av, 3, 0, nil); cfd = kannounce("udp!*!68", dir); if(cfd < 0) return "dhcp announce failed"; strcat(dir, "/data"); if(kwrite(cfd, "headers", 7) < 0){ kclose(cfd); return "dhcp ctl headers failed"; } kwrite(cfd, "oldheaders", 10); dfd = kopen(dir, ORDWR); if(dfd < 0){ kclose(cfd); return "dhcp open data failed"; } kclose(cfd); while(tries<1){ tries++; memset(sid, 0, 4); iplease=0; dhcpmsgtype=-2; /* DHCPDISCOVER*/ done = 0; recv = 0; kproc("rcvbootp", rcvbootp, (void*)dfd, KPDUPFDG); /* Prepare DHCPDISCOVER */ memset(&req, 0, sizeof(req)); ipmove(req.raddr, IPv4bcast); hnputs(req.rport, 67); req.op = Bootrequest; req.htype = 1; /* ethernet (all we know) */ req.hlen = 6; /* ethernet (all we know) */ memmove(req.chaddr, ifc->mac, 6); /* Hardware MAC address */ //ipv4local(ifc, req.ciaddr); /* Fill in the local IP address if we know it */ memset(req.file, 0, sizeof(req.file)); vend=req.vend; memmove(vend, vend_rfc1048, 4); vend+=4; *vend++=53; *vend++=1;*vend++=1; /* dhcp msg type==3, dhcprequest */ *vend++=61;*vend++=7;*vend++=1; memmove(vend, ifc->mac, 6);vend+=6; *vend=0xff; if(debug) dispvend(req.vend); for(n=0;n<4;n++){ if(kwrite(dfd, &req, sizeof(req))<0) /* SEND DHCPDISCOVER */ print("DHCPDISCOVER: %r"); tsleep(&bootpr, return0, 0, 1000); /* wait DHCPOFFER */ if(debug) print("[DHCP] DISCOVER: msgtype = %d\n", dhcpmsgtype); if(dhcpmsgtype==2) /* DHCPOFFER */ break; else if(dhcpmsgtype==0) /* bootp */ return nil; else if(dhcpmsgtype== -2) /* time out */ continue; else break; } if(dhcpmsgtype!=2) continue; /* DHCPREQUEST */ memset(req.vend, 0, sizeof(req.vend)); vend=req.vend; memmove(vend, vend_rfc1048, 4);vend+=4; *vend++=53; *vend++=1;*vend++=3; /* dhcp msg type==3, dhcprequest */ *vend++=50; *vend++=4; /* requested ip address */ *vend++=(ipaddr >> 24)&0xff; *vend++=(ipaddr >> 16)&0xff; *vend++=(ipaddr >> 8) & 0xff; *vend++=ipaddr & 0xff; *vend++=51;*vend++=4; /* lease time */ *vend++=(iplease>>24)&0xff; *vend++=(iplease>>16)&0xff; *vend++=(iplease>>8)&0xff; *vend++=iplease&0xff; *vend++=54; *vend++=4; /* server identifier */ memmove(vend, sid, 4); vend+=4; *vend++=61;*vend++=07;*vend++=01; /* client identifier */ memmove(vend, ifc->mac, 6);vend+=6; *vend=0xff; if(debug) dispvend(req.vend); if(kwrite(dfd, &req, sizeof(req))<0){ print("DHCPREQUEST: %r"); continue; } tsleep(&bootpr, return0, 0, 2000); if(dhcpmsgtype==5) /* wait for DHCPACK */ break; else continue; /* CHECK ARP */ /* DHCPDECLINE */ } kclose(dfd); done = 1; if(rcvprocp != nil){ postnote(rcvprocp, 1, "timeout", 0); rcvprocp = nil; } av[1] = "0.0.0.0"; av[2] = "0.0.0.0"; ipifcrem(ifc, av, 3); hnputl(nipaddr, ipaddr); sprint(ia, "%V", nipaddr); hnputl(nipmask, ipmask); sprint(im, "%V", nipmask); av[1] = ia; av[2] = im; ipifcadd(ifc, av, 3, 0, nil); if(gwip != 0) { hnputl(ngwip, gwip); n = sprint(ia, "add 0.0.0.0 0.0.0.0 %V", ngwip); routewrite(ifc->conv->p->f, nil, ia, n); } return nil; }