int so_send(int sock, void *va, int len, void *hdr, int hdrlen) { int r; struct sockaddr sa; struct sockaddr_in *sin; uchar *h = hdr; osenter(); if(hdr == 0) r = send(sock, va, len, 0); else { memset(&sa, 0, sizeof(sa)); sin = (struct sockaddr_in*)&sa; sin->sin_family = AF_INET; switch(hdrlen){ case OUdphdrlenv4: memmove(&sin->sin_addr, h, 4); memmove(&sin->sin_port, h+8, 2); break; case OUdphdrlen: v6tov4((uchar*)&sin->sin_addr, h); memmove(&sin->sin_port, h+2*IPaddrlen, 2); /* rport */ break; default: v6tov4((uchar*)&sin->sin_addr, h); memmove(&sin->sin_port, h+3*IPaddrlen, 2); break; } r = sendto(sock, va, len, 0, &sa, sizeof(sa)); } osleave(); return r; }
void dhcpsend(int type) { int n; uint8_t *p; Bootp bp; Udphdr *up; memset(&bp, 0, sizeof bp); up = (Udphdr*)bp.udphdr; hnputs(up->rport, 67); bp.op = Bootrequest; hnputl(bp.xid, dhcp.xid); hnputs(bp.secs, time(0) - dhcp.starttime); hnputs(bp.flags, Fbroadcast); /* reply must be broadcast */ memmove(bp.optmagic, optmagic, 4); p = bp.optdata; p = optaddbyte(p, ODtype, type); p = optadd(p, ODclientid, dhcp.cid, strlen(dhcp.cid)); switch(type) { default: myfatal("dhcpsend: unknown message type: %d", type); case Discover: ipmove(up->raddr, IPv4bcast); /* broadcast */ break; case Request: if(dhcp.state == Sbound || dhcp.state == Srenewing) ipmove(up->raddr, dhcp.server); else ipmove(up->raddr, IPv4bcast); /* broadcast */ p = optaddulong(p, ODlease, dhcp.lease); if(dhcp.state == Sselecting || dhcp.state == Srequesting) { p = optaddaddr(p, ODipaddr, dhcp.client); /* mistake?? */ p = optaddaddr(p, ODserverid, dhcp.server); } else v6tov4(bp.ciaddr, dhcp.client); break; case Release: ipmove(up->raddr, dhcp.server); v6tov4(bp.ciaddr, dhcp.client); p = optaddaddr(p, ODipaddr, dhcp.client); p = optaddaddr(p, ODserverid, dhcp.server); break; } *p++ = OBend; n = p - (uint8_t*)&bp; if(write(dhcp.fd, &bp, n) != n) myfatal("dhcpsend: write failed: %r"); }
void relsendack(Conv *c, Reliable *r, int hangup) { Udphdr *uh; Block *bp; Rudphdr *rh; int ptcllen; Fs *f; bp = allocb(UDP_IPHDR + UDP_RHDRSIZE); if(bp == nil) return; bp->wp += UDP_IPHDR + UDP_RHDRSIZE; f = c->p->f; uh = (Udphdr *)(bp->rp); uh->vihl = IP_VER4; rh = (Rudphdr*)uh; ptcllen = (UDP_RHDRSIZE-UDP_PHDRSIZE); uh->Unused = 0; uh->udpproto = IP_UDPPROTO; uh->frag[0] = 0; uh->frag[1] = 0; hnputs(uh->udpplen, ptcllen); v6tov4(uh->udpdst, r->addr); hnputs(uh->udpdport, r->port); hnputs(uh->udpsport, c->lport); if(ipcmp(c->laddr, IPnoaddr) == 0) findlocalip(f, c->laddr, c->raddr); v6tov4(uh->udpsrc, c->laddr); hnputs(uh->udplen, ptcllen); if(hangup) hnputl(rh->relsgen, Hangupgen); else hnputl(rh->relsgen, r->sndgen); hnputl(rh->relseq, 0); hnputl(rh->relagen, r->rcvgen); hnputl(rh->relack, r->rcvseq); if(r->acksent < r->rcvseq) r->acksent = r->rcvseq; uh->udpcksum[0] = 0; uh->udpcksum[1] = 0; hnputs(uh->udpcksum, ptclcsum(bp, UDP_IPHDR, UDP_RHDRSIZE)); DPRINT("sendack: %lud/%lud, %lud/%lud\n", 0L, r->sndgen, r->rcvseq, r->rcvgen); doipoput(c, f, bp, 0, c->ttl, c->tos); }
uint8_t * optaddaddr(uint8_t *p, int op, uint8_t *ip) { p[0] = op; p[1] = 4; v6tov4(p+2, ip); return p+6; }
void readifcs(void) { Ipifc *ifc; Iplifc *lifc; Ifc *ip; Bnet *bn; Route route; int i; ifcs = readipifc(netdir, ifcs, -1); i = 0; for(ifc = ifcs; ifc != nil; ifc = ifc->next){ for(lifc = ifc->lifc; lifc != nil && i < Nifc; lifc = lifc->next){ // ignore any interfaces that aren't v4 if(memcmp(lifc->ip, v4prefix, IPaddrlen-IPv4addrlen) != 0) continue; ip = &ialloc.ifc[i++]; v6tov4(ip->addr, lifc->ip); v6tov4mask(ip->mask, lifc->mask); v6tov4(ip->net, lifc->net); ip->cmask = v4defmask(ip->net); v4maskip(ip->net, ip->cmask, ip->cnet); ip->bcast = 0; /* add as a route */ memmove(route.mask, ip->mask, Pasize); memmove(route.dest, ip->net, Pasize); memset(route.gate, 0, Pasize); route.metric = 0; considerroute(&route); /* mark as broadcast */ if(bnets == 0) ip->bcast = 1; else for(bn = bnets; bn; bn = bn->next) if(memcmp(bn->addr, ip->net, Pasize) == 0){ ip->bcast = 1; break; } } } ialloc.nifc = i; }
int str2addr(char *s, uchar *a) { uchar *a0, ip[16]; char *p; if((s = strchr(s, '!')) == nil) return 0; if((p = strchr(++s, '!')) == nil) return 0; if(strchr(++p, '!') != nil) return 0; if(parseip(ip, s) == -1) return 0; a0 = a; if(socksver == 4){ a += 2; hnputs(a, atoi(p)); a += 2; v6tov4(a, ip); a += 4; } else { a += 3; if(isv4(ip)){ *a++ = 0x01; v6tov4(a, ip); a += 4; } else { *a++ = 0x04; memmove(a, ip, 16); a += 16; } hnputs(a, atoi(p)); a += 2; } return a - a0; }
void so_connect(int fd, unsigned char *raddr, unsigned short rport) { struct sockaddr_storage ss; memset(&ss, 0, sizeof(ss)); ss.ss_family = family(raddr); switch(ss.ss_family){ case AF_INET: hnputs(&((struct sockaddr_in*)&ss)->sin_port, rport); v6tov4((unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr, raddr); break; case AF_INET6: hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, rport); memcpy(&((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, raddr, sizeof(struct in6_addr)); break; } if(connect(fd, (struct sockaddr*)&ss, addrlen(&ss)) < 0) oserror(); }
void udpkick(void *x, struct block *bp) { struct conv *c = x; Udp4hdr *uh4; Udp6hdr *uh6; uint16_t rport; uint8_t laddr[IPaddrlen], raddr[IPaddrlen]; Udpcb *ucb; int dlen, ptcllen; Udppriv *upriv; struct Fs *f; int version; struct conv *rc; upriv = c->p->priv; assert(upriv); f = c->p->f; netlog(c->p->f, Logudp, "udp: kick\n"); if (bp == NULL) return; ucb = (Udpcb *) c->ptcl; switch (ucb->headers) { case 7: /* get user specified addresses */ bp = pullupblock(bp, UDP_USEAD7); if (bp == NULL) return; ipmove(raddr, bp->rp); bp->rp += IPaddrlen; ipmove(laddr, bp->rp); bp->rp += IPaddrlen; /* pick interface closest to dest */ if (ipforme(f, laddr) != Runi) findlocalip(f, laddr, raddr); bp->rp += IPaddrlen; /* Ignore ifc address */ rport = nhgets(bp->rp); bp->rp += 2 + 2; /* Ignore local port */ break; case 6: /* get user specified addresses */ bp = pullupblock(bp, UDP_USEAD6); if (bp == NULL) return; ipmove(raddr, bp->rp); bp->rp += IPaddrlen; ipmove(laddr, bp->rp); bp->rp += IPaddrlen; /* pick interface closest to dest */ if (ipforme(f, laddr) != Runi) findlocalip(f, laddr, raddr); rport = nhgets(bp->rp); bp->rp += 2 + 2; /* Ignore local port */ break; default: rport = 0; break; } if (ucb->headers) { if (memcmp(laddr, v4prefix, IPv4off) == 0 || ipcmp(laddr, IPnoaddr) == 0) version = V4; else version = V6; } else { if ((memcmp(c->raddr, v4prefix, IPv4off) == 0 && memcmp(c->laddr, v4prefix, IPv4off) == 0) || ipcmp(c->raddr, IPnoaddr) == 0) version = V4; else version = V6; } dlen = blocklen(bp); /* fill in pseudo header and compute checksum */ switch (version) { case V4: bp = padblock(bp, UDP4_IPHDR_SZ + UDP_UDPHDR_SZ); if (bp == NULL) return; uh4 = (Udp4hdr *) (bp->rp); ptcllen = dlen + UDP_UDPHDR_SZ; uh4->Unused = 0; uh4->udpproto = IP_UDPPROTO; uh4->frag[0] = 0; uh4->frag[1] = 0; hnputs(uh4->udpplen, ptcllen); if (ucb->headers) { v6tov4(uh4->udpdst, raddr); hnputs(uh4->udpdport, rport); v6tov4(uh4->udpsrc, laddr); rc = NULL; } else { v6tov4(uh4->udpdst, c->raddr); hnputs(uh4->udpdport, c->rport); if (ipcmp(c->laddr, IPnoaddr) == 0) findlocalip(f, c->laddr, c->raddr); v6tov4(uh4->udpsrc, c->laddr); rc = c; } hnputs(uh4->udpsport, c->lport); hnputs(uh4->udplen, ptcllen); uh4->udpcksum[0] = 0; uh4->udpcksum[1] = 0; hnputs(uh4->udpcksum, ~ptclcsum(bp, UDP4_PHDR_OFF, UDP4_PHDR_SZ)); bp->checksum_start = UDP4_IPHDR_SZ; bp->checksum_offset = uh4->udpcksum - uh4->udpsport; bp->flag |= Budpck; uh4->vihl = IP_VER4; ipoput4(f, bp, 0, c->ttl, c->tos, rc); break; case V6: bp = padblock(bp, UDP6_IPHDR_SZ + UDP_UDPHDR_SZ); if (bp == NULL) return; // using the v6 ip header to create pseudo header // first then reset it to the normal ip header uh6 = (Udp6hdr *) (bp->rp); memset(uh6, 0, 8); ptcllen = dlen + UDP_UDPHDR_SZ; hnputl(uh6->viclfl, ptcllen); uh6->hoplimit = IP_UDPPROTO; if (ucb->headers) { ipmove(uh6->udpdst, raddr); hnputs(uh6->udpdport, rport); ipmove(uh6->udpsrc, laddr); rc = NULL; } else { ipmove(uh6->udpdst, c->raddr); hnputs(uh6->udpdport, c->rport); if (ipcmp(c->laddr, IPnoaddr) == 0) findlocalip(f, c->laddr, c->raddr); ipmove(uh6->udpsrc, c->laddr); rc = c; } hnputs(uh6->udpsport, c->lport); hnputs(uh6->udplen, ptcllen); uh6->udpcksum[0] = 0; uh6->udpcksum[1] = 0; hnputs(uh6->udpcksum, ptclcsum(bp, UDP6_PHDR_OFF, dlen + UDP_UDPHDR_SZ + UDP6_PHDR_SZ)); memset(uh6, 0, 8); uh6->viclfl[0] = IP_VER6; hnputs(uh6->len, ptcllen); uh6->nextheader = IP_UDPPROTO; ipoput6(f, bp, 0, c->ttl, c->tos, rc); break; default: panic("udpkick: version %d", version); } upriv->ustats.udpOutDatagrams++; }
/* * encapsulate next IP packet on x's write queue in IP/ESP packet * and initiate output of the result. */ static void espkick(void *x) { int nexthdr, payload, pad, align; uint8_t *auth; Block *bp; Conv *c = x; Esp4hdr *eh4; Esp6hdr *eh6; Espcb *ecb; Esptail *et; Userhdr *uh; Versdep vers; getverslens(convipvers(c), &vers); bp = qget(c->wq); if(bp == nil) return; qlock(c); ecb = c->ptcl; if(ecb->header) { /* make sure the message has a User header */ bp = pullupblock(bp, Userhdrlen); if(bp == nil) { qunlock(c); return; } uh = (Userhdr*)bp->rp; nexthdr = uh->nexthdr; bp->rp += Userhdrlen; } else { nexthdr = 0; /* what should this be? */ } payload = BLEN(bp) + ecb->espivlen; /* Make space to fit ip header */ bp = padblock(bp, vers.hdrlen + ecb->espivlen); getpktspiaddrs(bp->rp, &vers); align = 4; if(ecb->espblklen > align) align = ecb->espblklen; if(align % ecb->ahblklen != 0) panic("espkick: ahblklen is important after all"); pad = (align-1) - (payload + Esptaillen-1)%align; /* * Make space for tail * this is done by calling padblock with a negative size * Padblock does not change bp->wp! */ bp = padblock(bp, -(pad+Esptaillen+ecb->ahlen)); bp->wp += pad+Esptaillen+ecb->ahlen; et = (Esptail*)(bp->rp + vers.hdrlen + payload + pad); /* fill in tail */ et->pad = pad; et->nexthdr = nexthdr; /* encrypt the payload */ ecb->cipher(ecb, bp->rp + vers.hdrlen, payload + pad + Esptaillen); auth = bp->rp + vers.hdrlen + payload + pad + Esptaillen; /* fill in head; construct a new IP header and an ESP header */ if (vers.version == V4) { eh4 = (Esp4hdr *)bp->rp; eh4->vihl = IP_VER4; v6tov4(eh4->espsrc, c->laddr); v6tov4(eh4->espdst, c->raddr); eh4->espproto = IP_ESPPROTO; eh4->frag[0] = 0; eh4->frag[1] = 0; hnputl(eh4->espspi, ecb->spi); hnputl(eh4->espseq, ++ecb->seq); } else { eh6 = (Esp6hdr *)bp->rp; eh6->vcf[0] = IP_VER6; ipmove(eh6->src, c->laddr); ipmove(eh6->dst, c->raddr); eh6->proto = IP_ESPPROTO; hnputl(eh6->espspi, ecb->spi); hnputl(eh6->espseq, ++ecb->seq); } /* compute secure hash */ ecb->auth(ecb, bp->rp + vers.iphdrlen, (vers.hdrlen - vers.iphdrlen) + payload + pad + Esptaillen, auth); qunlock(c); /* print("esp: pass down: %uld\n", BLEN(bp)); */ if (vers.version == V4) ipoput4(c->p->f, bp, 0, c->ttl, c->tos, c); else ipoput6(c->p->f, bp, 0, c->ttl, c->tos, c); }
int so_recv(int sock, void *va, int len, void *hdr, int hdrlen) { int r, l; struct sockaddr_storage sa; struct sockaddr_in6 *sin6; char h[Udphdrlen]; osenter(); if(hdr == 0) r = read(sock, va, len); else { sin6 = (struct sockaddr_in6*)&sa; l = sizeof(sa); r = recvfrom(sock, va, len, 0, (struct sockaddr*)&sa, &l); if(r >= 0) { memset(h, 0, sizeof(h)); switch(hdrlen){ case OUdphdrlenv4: if(v6tov4(h, (uchar*)&sin6->sin6_addr) < 0) { osleave(); error("OUdphdrlenv4 with IPv6 address"); } memmove(h+2*IPv4addrlen, &sin6->sin6_port, 2); break; case OUdphdrlen: memmove(h, (uchar*)&sin6->sin6_addr, IPaddrlen); memmove(h+2*IPaddrlen, &sin6->sin6_port, 2); break; default: memmove(h, (uchar*)&sin6->sin6_addr, IPaddrlen); memmove(h+3*IPaddrlen, &sin6->sin6_port, 2); break; } /* alas there's no way to get the local addr/port correctly. Pretend. */ memset(&sa, 0, sizeof(sa)); l = sizeof(sa); getsockname(sock, (struct sockaddr*)&sa, &l); switch(hdrlen){ case OUdphdrlenv4: /* * we get v6Unspecified/noaddr if local address cannot be determined. * that's reasonable for ipv4 too. */ if(ipcmp(v6Unspecified, (uchar*)&sin6->sin6_addr) != 0 && v6tov4(h+IPv4addrlen, (uchar*)&sin6->sin6_addr) < 0) { osleave(); error("OUdphdrlenv4 with IPv6 address"); } memmove(h+2*IPv4addrlen+2, &sin6->sin6_port, 2); break; case OUdphdrlen: memmove(h+IPaddrlen, (uchar*)&sin6->sin6_addr, IPaddrlen); memmove(h+2*IPaddrlen+2, &sin6->sin6_port, 2); break; default: memmove(h+IPaddrlen, (uchar*)&sin6->sin6_addr, IPaddrlen); memmove(h+2*IPaddrlen, (uchar*)&sin6->sin6_addr, IPaddrlen); /* ifcaddr */ memmove(h+3*IPaddrlen+2, &sin6->sin6_port, 2); break; } memmove(hdr, h, hdrlen); } } osleave(); return r; }
void sender(int fd, int msglen, int interval, int n) { int i, extra; uint16_t seq; char *buf = malloc(BUFSIZE); uint8_t me[IPaddrlen], mev4[IPv4addrlen]; struct icmphdr *icmp; Req *r; firstseq = seq = rand(); icmp = geticmp(buf); memset(buf, 0, proto->iphdrsz + ICMP_HDRSIZE); for(i = proto->iphdrsz + ICMP_HDRSIZE; i < msglen; i++) buf[i] = i; icmp->type = proto->echocmd; icmp->code = 0; /* arguably the kernel should fill in the right src addr. */ myipvnaddr(me, proto, network); if (proto->version == 4) { v6tov4(mev4, me); memmove(((struct ip4hdr *)buf)->src, mev4, IPv4addrlen); } else ipmove(((struct ip6hdr *)buf)->src, me); if (addresses) printf("\t%i -> %s\n", me, target); if(pingrint != 0 && interval <= 0) pingrint = 0; extra = 0; for(i = 0; i < n; i++){ if(i != 0){ if(pingrint != 0) extra = rand(); /* uth_sleep takes seconds, interval is in ms */ uthread_usleep((interval + extra) * 1000); } r = calloc(sizeof *r, 1); if (r == NULL){ printf("out of memory? \n"); break; } hnputs(icmp->seq, seq); r->seq = seq; r->next = NULL; r->replied = 0; r->tsctime = read_tsc(); /* avoid early free in reply! */ spin_pdr_lock(&listlock); if(first == NULL) first = r; else last->next = r; last = r; spin_pdr_unlock(&listlock); r->tsctime = read_tsc(); if(write(fd, buf, msglen) < msglen){ fprintf(stderr, "%s: write failed: %r\n", argv0); return; } seq++; } done = 1; }
void rudpkick(void *x) { Proc *up = externup(); Conv *c = x; Udphdr *uh; uint16_t rport; uint8_t laddr[IPaddrlen], raddr[IPaddrlen]; Block *bp; Rudpcb *ucb; Rudphdr *rh; Reliable *r; int dlen, ptcllen; Rudppriv *upriv; Fs *f; upriv = c->p->priv; f = c->p->f; netlog(c->p->f, Logrudp, "rudp: kick\n"); bp = qget(c->wq); if(bp == nil) return; ucb = (Rudpcb*)c->ptcl; switch(ucb->headers) { case 7: /* get user specified addresses */ bp = pullupblock(bp, UDP_USEAD7); if(bp == nil) return; ipmove(raddr, bp->rp); bp->rp += IPaddrlen; ipmove(laddr, bp->rp); bp->rp += IPaddrlen; /* pick interface closest to dest */ if(ipforme(f, laddr) != Runi) findlocalip(f, laddr, raddr); bp->rp += IPaddrlen; /* Ignore ifc address */ rport = nhgets(bp->rp); bp->rp += 2+2; /* Ignore local port */ break; default: ipmove(raddr, c->raddr); ipmove(laddr, c->laddr); rport = c->rport; break; } dlen = blocklen(bp); /* Make space to fit rudp & ip header */ bp = padblock(bp, UDP_IPHDR+UDP_RHDRSIZE); if(bp == nil) return; uh = (Udphdr *)(bp->rp); uh->vihl = IP_VER4; rh = (Rudphdr*)uh; ptcllen = dlen + (UDP_RHDRSIZE-UDP_PHDRSIZE); uh->Unused = 0; uh->udpproto = IP_UDPPROTO; uh->frag[0] = 0; uh->frag[1] = 0; hnputs(uh->udpplen, ptcllen); switch(ucb->headers){ case 7: v6tov4(uh->udpdst, raddr); hnputs(uh->udpdport, rport); v6tov4(uh->udpsrc, laddr); break; default: v6tov4(uh->udpdst, c->raddr); hnputs(uh->udpdport, c->rport); if(ipcmp(c->laddr, IPnoaddr) == 0) findlocalip(f, c->laddr, c->raddr); v6tov4(uh->udpsrc, c->laddr); break; } hnputs(uh->udpsport, c->lport); hnputs(uh->udplen, ptcllen); uh->udpcksum[0] = 0; uh->udpcksum[1] = 0; qlock(&ucb->ql); r = relstate(ucb, raddr, rport, "kick"); r->sndseq = NEXTSEQ(r->sndseq); hnputl(rh->relseq, r->sndseq); hnputl(rh->relsgen, r->sndgen); hnputl(rh->relack, r->rcvseq); /* ACK last rcvd packet */ hnputl(rh->relagen, r->rcvgen); if(r->rcvseq != r->acksent) r->acksent = r->rcvseq; hnputs(uh->udpcksum, ptclcsum(bp, UDP_IPHDR, dlen+UDP_RHDRSIZE)); relackq(r, bp); qunlock(&ucb->ql); upriv->ustats.rudpOutDatagrams++; DPRINT("sent: %lud/%lud, %lud/%lud\n", r->sndseq, r->sndgen, r->rcvseq, r->rcvgen); doipoput(c, f, bp, 0, c->ttl, c->tos); if(waserror()) { relput(r); qunlock(&r->lock); nexterror(); } /* flow control of sorts */ qlock(&r->lock); if(UNACKED(r) > Maxunacked){ r->blocked = 1; sleep(&r->vous, flow, r); r->blocked = 0; } qunlock(&r->lock); relput(r); poperror(); }
int udprelay(int fd, char *dir) { struct { Udphdr; uchar data[8*1024]; } msg; char addr[128], ldir[40]; int r, n, rfd, cfd; uchar *p; snprint(addr, sizeof(addr), "%s/udp!*!0", outside); if((cfd = announce(addr, ldir)) < 0) return -1; if(write(cfd, "headers", 7) != 7) return -1; strcat(ldir, "/data"); if((rfd = open(ldir, ORDWR)) < 0) return -1; close(cfd); if((r = rfork(RFMEM|RFPROC|RFNOWAIT)) <= 0) return r; if((cfd = listen(dir, ldir)) < 0) return -1; close(fd); /* close inside udp server */ if((fd = accept(cfd, ldir)) < 0) return -1; switch(rfork(RFMEM|RFPROC|RFNOWAIT)){ case -1: return -1; case 0: while((r = read(fd, msg.data, sizeof(msg.data))) > 0){ if(r < 4) continue; p = msg.data; if(p[0] | p[1] | p[2]) continue; p += 3; switch(*p++){ default: continue; case 0x01: r -= 2+1+1+4+2; if(r < 0) continue; v4tov6(msg.raddr, p); p += 4; break; case 0x04: r -= 2+1+1+16+2; if(r < 0) continue; memmove(msg.raddr, p, 16); p += 16; break; } memmove(msg.rport, p, 2); p += 2; memmove(msg.data, p, r); write(rfd, &msg, sizeof(Udphdr)+r); } break; default: while((r = read(rfd, &msg, sizeof(msg))) > 0){ r -= sizeof(Udphdr); if(r < 0) continue; p = msg.data; if(isv4(msg.raddr)) n = 2+1+1+4+2; else n = 2+1+1+16+2; if(r+n > sizeof(msg.data)) r = sizeof(msg.data)-n; memmove(p+n, p, r); *p++ = 0; *p++ = 0; *p++ = 0; if(isv4(msg.raddr)){ *p++ = 0x01; v6tov4(p, msg.raddr); p += 4; } else { *p++ = 0x04; memmove(p, msg.raddr, 16); p += 16; } memmove(p, msg.rport, 2); r += n; write(fd, msg.data, r); } } return -1; }
void main(int argc, char *argv[]) { int dobroadcast, i, n; long diff; char *p; char buf[2*1024]; uint8_t raddr[Pasize]; Bnet *bn, **l; Udphdr *up; Rip *r; Ripmsg *m; Route route; static long btime; setnetmtpt(netdir, sizeof(netdir), nil); dobroadcast = 0; ARGBEGIN{ case 'b': dobroadcast++; break; case 'd': debug++; break; case 'n': readonly++; break; case 'x': p = ARGF(); if(p == nil) usage(); setnetmtpt(netdir, sizeof(netdir), p); break; default: usage(); }ARGEND /* specific broadcast nets */ l = &bnets; while(argc > 0){ bn = (Bnet*)malloc(sizeof(Bnet)); if(bn == 0) fatal(1, "out of mem"); v4parseip(bn->addr, *argv); *l = bn; l = &bn->next; argc--; argv++; dobroadcast++; } /* command returns */ if(!debug) switch(rfork(RFNOTEG|RFPROC|RFFDG|RFNOWAIT)) { case -1: fatal(1, "fork"); case 0: break; default: exits(0); } fmtinstall('E', eipfmt); fmtinstall('V', eipfmt); snprint(routefile, sizeof(routefile), "%s/iproute", netdir); snprint(buf, sizeof(buf), "%s/iproute", netdir); now = time(0); readifcs(); readroutes(); notify(ding); ripfd = openport(); for(;;) { diff = btime - time(0); if(diff <= 0){ if(dobroadcast) broadcast(); timeoutroutes(); btime = time(0) + 2*60; diff = 2*60; } alarm(diff*1000); n = read(ripfd, buf, sizeof(buf)); alarm(0); if(n <= 0) continue; n = (n - Udphdrsize - 4) / sizeof(Rip); if(n <= 0) continue; up = (Udphdr*)buf; m = (Ripmsg*)(buf+Udphdrsize); if(m->type != Response || m->vers != Version) continue; v6tov4(raddr, up->raddr); /* ignore our own messages */ for(i = 0; i < ialloc.nifc; i++) if(equivip(ialloc.ifc[i].addr, raddr)) continue; now = time(0); for(r = m->rip; r < &m->rip[n]; r++){ memmove(route.gate, raddr, Pasize); memmove(route.mask, getmask(r->addr), Pasize); v4maskip(r->addr, route.mask, route.dest); route.metric = nhgetl(r->metric) + 1; if(route.metric < 1) continue; considerroute(&route); } } /* not reached */ }
static void espkick(void *x) { Conv *c = x; Esphdr *eh; Esptail *et; Userhdr *uh; Espcb *ecb; Block *bp; int nexthdr; int payload; int pad; int align; uchar *auth; bp = qget(c->wq); if(bp == nil) return; qlock(c); ecb = c->ptcl; if(ecb->header) { /* make sure the message has a User header */ bp = pullupblock(bp, UserhdrSize); if(bp == nil) { qunlock(c); return; } uh = (Userhdr*)bp->rp; nexthdr = uh->nexthdr; bp->rp += UserhdrSize; } else { nexthdr = 0; // what should this be? } payload = BLEN(bp) + ecb->espivlen; /* Make space to fit ip header */ bp = padblock(bp, EsphdrSize + ecb->espivlen); align = 4; if(ecb->espblklen > align) align = ecb->espblklen; if(align % ecb->ahblklen != 0) panic("espkick: ahblklen is important after all"); pad = (align-1) - (payload + EsptailSize-1)%align; /* * Make space for tail * this is done by calling padblock with a negative size * Padblock does not change bp->wp! */ bp = padblock(bp, -(pad+EsptailSize+ecb->ahlen)); bp->wp += pad+EsptailSize+ecb->ahlen; eh = (Esphdr *)(bp->rp); et = (Esptail*)(bp->rp + EsphdrSize + payload + pad); // fill in tail et->pad = pad; et->nexthdr = nexthdr; ecb->cipher(ecb, bp->rp+EsphdrSize, payload+pad+EsptailSize); auth = bp->rp + EsphdrSize + payload + pad + EsptailSize; // fill in head eh->vihl = IP_VER4; hnputl(eh->espspi, ecb->spi); hnputl(eh->espseq, ++ecb->seq); v6tov4(eh->espsrc, c->laddr); v6tov4(eh->espdst, c->raddr); eh->espproto = IP_ESPPROTO; eh->frag[0] = 0; eh->frag[1] = 0; ecb->auth(ecb, bp->rp+IphdrSize, (EsphdrSize-IphdrSize)+payload+pad+EsptailSize, auth); qunlock(c); //print("esp: pass down: %uld\n", BLEN(bp)); ipoput4(c->p->f, bp, 0, c->ttl, c->tos, c); }