/* * associate an address with the interface. This wipes out any previous * addresses. This is a macro that means, remove all the old interfaces * and add a new one. */ static char* ipifcconnect(Conv* c, char **argv, int argc) { Proc *up = externup(); char *err; Ipifc *ifc; ifc = (Ipifc*)c->ptcl; if(ifc->medium == nil) return "ipifc not yet bound to device"; if(waserror()){ wunlock(ifc); nexterror(); } wlock(ifc); while(ifc->lifc){ err = ipifcremlifc(ifc, ifc->lifc); if(err) error(err); } wunlock(ifc); poperror(); err = ipifcadd(ifc, argv, argc, 0, nil); if(err) return err; Fsconnected(c, nil); return nil; }
/* * associate an address with the interface. This wipes out any previous * addresses. This is a macro that means, remove all the old interfaces * and add a new one. */ static char *ipifcconnect(struct conv *c, char **argv, int argc) { ERRSTACK(1); char *err; struct Ipifc *ifc; ifc = (struct Ipifc *)c->ptcl; if (ifc->m == NULL) return "ipifc not yet bound to device"; if (waserror()) { wunlock(&ifc->rwlock); nexterror(); } wlock(&ifc->rwlock); while (ifc->lifc) { err = ipifcremlifc(ifc, ifc->lifc); if (err) error(err); } wunlock(&ifc->rwlock); poperror(); err = ipifcadd(ifc, argv, argc, 0, NULL); if (err) return err; Fsconnected(c, NULL); return NULL; }
char *ipifcaddpref6(struct Ipifc *ifc, char **argv, int argc) { uint8_t onlink = 1; uint8_t autoflag = 1; uint64_t validlt = UINT64_MAX; uint64_t preflt = UINT64_MAX; uint64_t origint = NOW / 10 ^ 3; uint8_t prefix[IPaddrlen]; int plen = 64; struct Iplifc *lifc; char addr[40], preflen[6]; char *params[3]; switch (argc) { case 7: preflt = atoi(argv[6]); /* fall through */ case 6: validlt = atoi(argv[5]); /* fall through */ case 5: autoflag = atoi(argv[4]); /* fall through */ case 4: onlink = atoi(argv[3]); /* fall through */ case 3: plen = atoi(argv[2]); case 2: break; default: return Ebadarg; } if ((parseip(prefix, argv[1]) != 6) || (validlt < preflt) || (plen < 0) || (plen > 64) || (islinklocal(prefix)) ) return Ebadarg; lifc = kzmalloc(sizeof(struct Iplifc), 0); lifc->onlink = (onlink != 0); lifc->autoflag = (autoflag != 0); lifc->validlt = validlt; lifc->preflt = preflt; lifc->origint = origint; if (ifc->m->pref2addr != NULL) ifc->m->pref2addr(prefix, ifc->mac); else return Ebadarg; snprintf(addr, sizeof(addr), "%I", prefix); snprintf(preflen, sizeof(preflen), "/%d", plen); params[0] = "add"; params[1] = addr; params[2] = preflen; return ipifcadd(ifc, params, 3, 0, lifc); }
/* * non-standard control messages. * called with c locked. */ static char *ipifcctl(struct conv *c, char **argv, int argc) { struct Ipifc *ifc; int i; ifc = (struct Ipifc *)c->ptcl; if (strcmp(argv[0], "add") == 0) return ipifcadd(ifc, argv, argc, 0, NULL); else if (strcmp(argv[0], "bootp") == 0) return bootp(ifc); else if (strcmp(argv[0], "try") == 0) return ipifcadd(ifc, argv, argc, 1, NULL); else if (strcmp(argv[0], "remove") == 0) return ipifcrem(ifc, argv, argc); else if (strcmp(argv[0], "unbind") == 0) return ipifcunbind(ifc); else if (strcmp(argv[0], "joinmulti") == 0) return ipifcjoinmulti(ifc, argv, argc); else if (strcmp(argv[0], "leavemulti") == 0) return ipifcleavemulti(ifc, argv, argc); else if (strcmp(argv[0], "mtu") == 0) return ipifcsetmtu(ifc, argv, argc); else if (strcmp(argv[0], "reassemble") == 0) { ifc->reassemble = 1; return NULL; } else if (strcmp(argv[0], "iprouting") == 0) { i = 1; if (argc > 1) i = atoi(argv[1]); iprouting(c->p->f, i); return NULL; } else if (strcmp(argv[0], "addpref6") == 0) return ipifcaddpref6(ifc, argv, argc); else if (strcmp(argv[0], "setpar6") == 0) return ipifcsetpar6(ifc, argv, argc); else if (strcmp(argv[0], "sendra6") == 0) return ipifcsendra6(ifc, argv, argc); else if (strcmp(argv[0], "recvra6") == 0) return ipifcrecvra6(ifc, argv, argc); return "unsupported ctl"; }
/* * non-standard control messages. * called with c->car locked. */ static char* ipifcctl(Conv* c, char**argv, int argc) { Ipifc *ifc; int i; ifc = (Ipifc*)c->ptcl; if(strcmp(argv[0], "add") == 0) return ipifcadd(ifc, argv, argc, 0, nil); else if(strcmp(argv[0], "try") == 0) return ipifcadd(ifc, argv, argc, 1, nil); else if(strcmp(argv[0], "remove") == 0) return ipifcrem(ifc, argv, argc); else if(strcmp(argv[0], "unbind") == 0) return ipifcunbind(ifc); else if(strcmp(argv[0], "joinmulti") == 0) return ipifcjoinmulti(ifc, argv, argc); else if(strcmp(argv[0], "leavemulti") == 0) return ipifcleavemulti(ifc, argv, argc); else if(strcmp(argv[0], "mtu") == 0) return ipifcsetmtu(ifc, argv, argc); else if(strcmp(argv[0], "reassemble") == 0){ ifc->reassemble = 1; return nil; } else if(strcmp(argv[0], "iprouting") == 0){ i = 1; if(argc > 1) i = atoi(argv[1]); iprouting(c->p->f, i); return nil; } else if(strcmp(argv[0], "add6") == 0) return ipifcadd6(ifc, argv, argc); else if(strcmp(argv[0], "ra6") == 0) return ipifcra6(ifc, argv, argc); return "unsupported ctl"; }
char* ipifcadd6(Ipifc *ifc, char**argv, int argc) { int plen = 64; int32_t origint = NOW / 1000, preflt = ~0L, validlt = ~0L; char addr[Maxv6repr], preflen[6]; char *params[3]; uint8_t autoflag = 1, onlink = 1; uint8_t prefix[IPaddrlen]; Iplifc *lifc; switch(argc) { case 7: preflt = atoi(argv[6]); /* fall through */ case 6: validlt = atoi(argv[5]); /* fall through */ case 5: autoflag = atoi(argv[4]); /* fall through */ case 4: onlink = atoi(argv[3]); /* fall through */ case 3: plen = atoi(argv[2]); /* fall through */ case 2: break; default: return Ebadarg; } if (parseip(prefix, argv[1]) != 6) return "bad ipv6 address"; if (validlt < preflt) return "valid ipv6 lifetime less than preferred lifetime"; if (plen < 0) return "negative ipv6 prefix length"; /* i think that this length limit is bogus - geoff */ // if (plen > 64) // return "ipv6 prefix length greater than 64; if (islinklocal(prefix)) return "ipv6 prefix is link-local"; lifc = smalloc(sizeof(Iplifc)); lifc->onlink = (onlink != 0); lifc->autoflag = (autoflag != 0); lifc->validlt = validlt; lifc->preflt = preflt; lifc->origint = origint; /* issue "add" ctl msg for v6 link-local addr and prefix len */ if(!ifc->medium->pref2addr) return "no pref2addr on interface"; ifc->medium->pref2addr(prefix, ifc->mac); /* mac → v6 link-local addr */ snprint(addr, sizeof addr, "%I", prefix); snprint(preflen, sizeof preflen, "/%d", plen); params[0] = "add"; params[1] = addr; params[2] = preflen; return ipifcadd(ifc, params, 3, 0, lifc); }
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; }