int nbdgramsendto(uint8_t *ipaddr, uint16_t port, NbDgram *s) { Udphdr *u; uint8_t msg[NbDgramMaxPacket + Udphdrsize]; int l; int rv; char *e; e = startlistener(); if (e != nil) return 0; l = nbdgramconvS2M(msg + nbudphdrsize, msg + sizeof(msg), s); if (l == 0) { print("conv failed\n"); return 0; } u = (Udphdr *)msg; ipmove(u->laddr, nbglobals.myipaddr); hnputs(u->lport, NbDgramPort); ipmove(u->raddr, ipaddr); hnputs(u->rport, port); //nbdumpdata(msg, l + nbudphdrsize); //print("transmitting\n"); rv = write(udp.fd, msg, l + nbudphdrsize); //print("rv %d l %d hdrsize %d error %r\n", rv, l, nbudphdrsize); return rv == l + nbudphdrsize; }
static void discover(int major, int minor) { Aoehdr *h; Block *b; Netlink *nl, *e; nl = netlinks.nl; e = nl + nelem(netlinks.nl); for(; nl < e; nl++){ if(nl->cc == nil) continue; b = allocb(ETHERMINTU); if(waserror()){ freeb(b); nexterror(); } b->wp = b->rp + ETHERMINTU; memset(b->rp, 0, ETHERMINTU); h = (Aoehdr*)b->rp; memset(h->dst, 0xff, sizeof h->dst); memmove(h->src, nl->ea, sizeof h->src); hnputs(h->type, Aoetype); h->verflag = Aoever << 4; hnputs(h->major, major); h->minor = minor; h->cmd = ACconfig; poperror(); /* send b down the queue */ devtab[nl->dc->type]->bwrite(nl->dc, b, 0); } }
static int hset(Aoedev *d, Frame *f, Aoehdr *h, int cmd) { int i; Devlink *l; l = pickdevlink(d); i = pickea(l); if(i == -1){ downdev(d, "resend fails; no netlink/ea"); return -1; } if(f->srb && sys->ticks - f->srb->ticksent > Srbtimeout){ eventlog("%æ: srb timeout\n", d); frameerror(d, f, Etimedout); return -1; } memmove(h->dst, l->eatab[i], Eaddrlen); memmove(h->src, l->nl->ea, sizeof h->src); hnputs(h->type, Aoetype); h->verflag = Aoever << 4; h->error = 0; hnputs(h->major, d->major); h->minor = d->minor; h->cmd = cmd; hnputl(h->tag, f->tag = newtag(d)); f->dl = l; f->nl = l->nl; f->eaidx = i; f->ticksent = sys->ticks; return f->tag; }
int tag(uint8_t *pkt, int type, void *value, int nvalue) { Taghdr *h; h = (Taghdr*)pkt; hnputs(h->type, type); hnputs(h->length, nvalue); memmove(pkt+4, value, nvalue); return 4+nvalue; }
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"); }
static void w_txstart(Ether* ether) { Etherpkt *pkt; Ctlr *ctlr; Block *bp; int len, off; if((ctlr = ether->ctlr) == nil || (ctlr->state & (Attached|Power)) != (Attached|Power) || ctlr->txbusy) return; if((bp = qget(ether->oq)) == nil) return; pkt = (Etherpkt*)bp->rp; // // If the packet header type field is > 1500 it is an IP or // ARP datagram, otherwise it is an 802.3 packet. See RFC1042. // memset(&ctlr->txf, 0, sizeof(ctlr->txf)); if(((pkt->type[0]<<8)|pkt->type[1]) > 1500){ ctlr->txf.framectl = WF_Data; memmove(ctlr->txf.addr1, pkt->d, Eaddrlen); memmove(ctlr->txf.addr2, pkt->s, Eaddrlen); memmove(ctlr->txf.dstaddr, pkt->d, Eaddrlen); memmove(ctlr->txf.srcaddr, pkt->s, Eaddrlen); memmove(&ctlr->txf.type, pkt->type, 2); bp->rp += ETHERHDRSIZE; len = BLEN(bp); off = WF_802_11_Off; ctlr->txf.dlen = len+ETHERHDRSIZE-WSnapHdrLen; hnputs((uchar*)&ctlr->txf.dat[0], WSnap0); hnputs((uchar*)&ctlr->txf.dat[1], WSnap1); hnputs((uchar*)&ctlr->txf.len, len+ETHERHDRSIZE-WSnapHdrLen); } else{ len = BLEN(bp); off = WF_802_3_Off; ctlr->txf.dlen = len; } w_write(ctlr, ctlr->txdid, 0, &ctlr->txf, sizeof(ctlr->txf)); w_write(ctlr, ctlr->txdid, off, bp->rp, len+2); if(w_cmd(ctlr, WCmdReclaim|WCmdTx, ctlr->txdid)){ DEBUG("wavelan: transmit failed\n"); ctlr->ntxerr++; } else{ ctlr->txbusy = 1; ctlr->txtmout = 2; } freeb(bp); }
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); }
void so_bind(int fd, int su, unsigned short port, unsigned char *addr) { int i, one; struct sockaddr_storage ss; one = 1; if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0){ oserrstr(); print("setsockopt: %r"); } if(su) { for(i = 600; i < 1024; i++) { memset(&ss, 0, sizeof(ss)); ss.ss_family = family(addr); switch(ss.ss_family){ case AF_INET: ((struct sockaddr_in*)&ss)->sin_port = i; break; case AF_INET6: ((struct sockaddr_in6*)&ss)->sin6_port = i; break; } if(bind(fd, (struct sockaddr*)&ss, addrlen(&ss)) >= 0) return; } oserror(); } memset(&ss, 0, sizeof(ss)); ss.ss_family = family(addr); switch(ss.ss_family){ case AF_INET: hnputs(&((struct sockaddr_in*)&ss)->sin_port, port); break; case AF_INET6: hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, port); break; } if(bind(fd, (struct sockaddr*)&ss, addrlen(&ss)) < 0) oserror(); }
int etherhdr(uint8_t *pkt, uint8_t *dst, int type) { Etherhdr *eh; eh = (Etherhdr*)pkt; memmove(eh->dst, dst, sizeof(eh->dst)); hnputs(eh->type, type); return EtherHdrSz; }
int pppoehdr(uint8_t *pkt, int code, int sessid) { Pppoehdr *ph; ph = (Pppoehdr*)pkt; ph->verstype = VersType; ph->code = code; hnputs(ph->sessid, sessid); return PppoeHdrSz; }
static int hset(Aoedev *d, Frame *f, Aoehdr *h, int cmd) { int i; Devlink *l; if(f->srb && MACHP(0)->ticks - f->srb->ticksent > Maxreqticks){ eventlog("%æ: srb timeout\n", d); if(cmd == ACata && f->srb && Nofail(d, s)) f->srb->ticksent = MACHP(0)->ticks; else frameerror(d, f, Etimedout); return -1; } l = pickdevlink(d); i = pickea(l); if(i == -1){ if(cmd != ACata || f->srb == nil || !Nofail(d, s)) downdev(d, "resend fails; no netlink/ea"); return -1; } memmove(h->dst, l->eatab[i], Eaddrlen); memmove(h->src, l->nl->ea, sizeof h->src); hnputs(h->type, Aoetype); h->verflag = Aoever << 4; h->error = 0; hnputs(h->major, d->major); h->minor = d->minor; h->cmd = cmd; hnputl(h->tag, f->tag = newtag(d)); f->dl = l; f->nl = l->nl; f->eaidx = i; f->ticksent = MACHP(0)->ticks; return f->tag; }
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 so_bind(int fd, int su, uchar *addr, ushort port) { int i, one; struct sockaddr_storage sa; struct sockaddr_in6 *sin6; sin6 = (struct sockaddr_in6*)&sa; one = 1; if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0) { oserrstr(up->genbuf, sizeof(up->genbuf)); print("setsockopt: %s", up->genbuf); } if(su) { for(i = 600; i < 1024; i++) { memset(&sa, 0, sizeof(sa)); sin6->sin6_family = AF_INET6; memmove(&sin6->sin6_addr, addr, IPaddrlen); hnputs(&sin6->sin6_port, i); if(bind(fd, (struct sockaddr*)sin6, sizeof(*sin6)) >= 0) return; } oserror(); } memset(&sa, 0, sizeof(sa)); sin6->sin6_family = AF_INET6; memmove(&sin6->sin6_addr, addr, IPaddrlen); hnputs(&sin6->sin6_port, port); if(bind(fd, (struct sockaddr*)sin6, sizeof(*sin6)) < 0) oserror(); }
void so_bind(int fd, int su, uchar *addr, ushort port) { int i, one; struct sockaddr sa; struct sockaddr_in *sin; sin = (struct sockaddr_in*)&sa; one = 1; // if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0) { // oserrstr(up->genbuf, sizeof(up->genbuf)); // print("setsockopt: %s", err); // } if(su) { for(i = 600; i < 1024; i++) { memset(&sa, 0, sizeof(sa)); sin->sin_family = AF_INET; memmove(&sin->sin_addr.s_addr, addr+IPv4off, IPv4addrlen); hnputs(&sin->sin_port, i); if(bind(fd, &sa, sizeof(sa)) >= 0) return; } oserror(); } memset(&sa, 0, sizeof(sa)); sin->sin_family = AF_INET; memmove(&sin->sin_addr.s_addr, addr+IPv4off, IPv4addrlen); hnputs(&sin->sin_port, port); if(bind(fd, &sa, sizeof(sa)) < 0) oserror(); }
NbnsTransaction * nbnstransactionnew(NbnsMessage *s, uchar *ipaddr) { NbnsTransaction *t; uchar msg[Udphdrsize + 576]; Udphdr *u; int len; startlistener(); len = nbnsconvS2M(s, msg + nbudphdrsize, sizeof(msg) - nbudphdrsize); if (len == 0) return 0; t = mallocz(sizeof(*t), 1); if (t == nil) return nil; t->id = s->id; t->c = chancreate(sizeof(NbnsMessage *), 3); if (t->c == nil) { free(t); return nil; } qlock(&transactionlist); t->next = transactionlist.head; transactionlist.head = t; qunlock(&transactionlist); u = (Udphdr *)msg; ipmove(u->laddr, nbglobals.myipaddr); hnputs(u->lport, NbnsPort); if (s->broadcast || ipaddr == nil) ipmove(u->raddr, nbglobals.bcastaddr); else ipmove(u->raddr, ipaddr); hnputs(u->rport, NbnsPort); write(udp.fd, msg, len + nbudphdrsize); return t; }
/* PPPoE Active Discovery Initiation */ int padi(uint8_t *pkt) { int sz, tagoff; uint8_t *length; sz = 0; sz += etherhdr(pkt+sz, etherbcast, EtherPppoeDiscovery); sz += pppoehdr(pkt+sz, CodeDiscInit, 0x0000); length = pkt+sz-2; tagoff = sz; sz += tag(pkt+sz, TagSrvName, srvname, strlen(srvname)); hnputs(length, sz-tagoff); return sz; }
/* PPPoE Active Discovery Request */ int padr(uint8_t *pkt) { int sz, tagoff; uint8_t *length; sz = 0; sz += etherhdr(pkt+sz, etherdst, EtherPppoeDiscovery); sz += pppoehdr(pkt+sz, CodeDiscReq, 0x0000); length = pkt+sz-2; tagoff = sz; sz += tag(pkt+sz, TagSrvName, srvname, strlen(srvname)); sz += tag(pkt+sz, TagAcName, acname, strlen(acname)); if(cookie) sz += tag(pkt+sz, TagAcCookie, cookie, cookielen); hnputs(length, sz-tagoff); return sz; }
void so_connect(int fd, unsigned long raddr, unsigned short rport) { int r; struct sockaddr sa; struct sockaddr_in *sin; memset(&sa, 0, sizeof(sa)); sin = (struct sockaddr_in*)&sa; sin->sin_family = AF_INET; hnputs(&sin->sin_port, rport); hnputl(&sin->sin_addr.s_addr, raddr); osenter(); r = connect(fd, &sa, sizeof(sa)); osleave(); if(r < 0) oserror(); }
void so_connect(int fd, uchar *raddr, ushort rport) { int r; struct sockaddr_storage sa; struct sockaddr_in6 *sin6; memset(&sa, 0, sizeof(sa)); sin6 = (struct sockaddr_in6*)&sa; sin6->sin6_family = AF_INET6; hnputs(&sin6->sin6_port, rport); memmove((uchar*)&sin6->sin6_addr, raddr, IPaddrlen); osenter(); r = connect(fd, (struct sockaddr*)sin6, sizeof(*sin6)); osleave(); if(r < 0) oserror(); }
static void grekick(void *x, Block *bp) { Conv *c = x; GREhdr *ghp; uchar laddr[IPaddrlen], raddr[IPaddrlen]; if(bp == nil) return; /* Make space to fit ip header (gre header already there) */ bp = padblock(bp, GRE_IPONLY); if(bp == nil) return; /* make sure the message has a GRE header */ bp = pullupblock(bp, GRE_IPONLY+GRE_IPPLUSGRE); if(bp == nil) return; ghp = (GREhdr *)(bp->rp); ghp->vihl = IP_VER4; if(!((GREpriv*)c->p->priv)->raw){ v4tov6(raddr, ghp->dst); if(ipcmp(raddr, v4prefix) == 0) memmove(ghp->dst, c->raddr + IPv4off, IPv4addrlen); v4tov6(laddr, ghp->src); if(ipcmp(laddr, v4prefix) == 0){ if(ipcmp(c->laddr, IPnoaddr) == 0) findlocalip(c->p->f, c->laddr, raddr); /* pick interface closest to dest */ memmove(ghp->src, c->laddr + IPv4off, IPv4addrlen); } hnputs(ghp->eproto, c->rport); } ghp->proto = IP_GREPROTO; ghp->frag[0] = 0; ghp->frag[1] = 0; ipoput4(c->p->f, bp, 0, c->ttl, c->tos, nil); }
/* * write out a packet trace */ void tracepkt(uint8_t *ps, int len) { struct pcap_pkthdr *goo; if(Mflag && len > Mflag) len = Mflag; if(pcap){ goo = (struct pcap_pkthdr*)(ps-16); goo->ts = pkttime; goo->caplen = len; goo->len = len; write(1, goo, len+16); } else { hnputs(ps-10, len); hnputl(ps-8, pkttime>>32); hnputl(ps-4, pkttime); write(1, ps-10, len+10); } }
void so_connect(int fd, uchar *raddr, ushort rport) { int r; struct sockaddr sa; struct sockaddr_in *sin; if(!isv4(raddr)) error(Enotv4); memset(&sa, 0, sizeof(sa)); sin = (struct sockaddr_in*)&sa; sin->sin_family = AF_INET; hnputs(&sin->sin_port, rport); memmove(&sin->sin_addr.s_addr, raddr+IPv4off, IPv4addrlen); osenter(); r = connect(fd, &sa, sizeof(sa)); osleave(); if(r < 0) oserror(); }
/* Purpose: Send i3 data on TCP socket * Note: To avoid copying of packets, the two sends are performed */ int send_tcp(char *p, int len, nw_skt_t fd) { char header[TCP_I3_HEADER_SIZE]; /* Send header */ header[0] = TCP_I3_HEADER_MAGIC; hnputs(header + 1, (uint16_t) len); if (send(fd, header, TCP_I3_HEADER_SIZE, 0) != TCP_I3_HEADER_SIZE) { perror("TCP header send"); return -1; } /* Send rest of the packet */ if (send(fd, p, len, 0) < len) { perror("TCP Send"); return -1; } return len; }
void igmpsendreport(Medium *m, uchar *addr) { IGMPpkt *p; Block *bp; bp = allocb(sizeof(IGMPpkt)); if(bp == nil) return; p = (IGMPpkt*)bp->wp; p->vihl = IP_VER4; bp->wp += IGMPPKTSZ; memset(bp->rp, 0, IGMPPKTSZ); hnputl(p->src, Mediumgetaddr(m)); hnputl(p->dst, Ipallsys); p->vertype = (1<<4) | IGMPreport; p->proto = IP_IGMPPROTO; memmove(p->group, addr, IPaddrlen); hnputs(p->igmpcksum, ptclcsum(bp, IGMP_IPHDRSIZE, IGMP_HDRSIZE)); netlog(Logigmp, "igmpreport %I\n", p->group); stats.outreports++; ipoput4(bp, 0, 1, DFLTTOS, nil); /* TTL of 1 */ }
/* * fast forwarding of incoming queries to other dns servers. * intended primarily for debugging. */ static void redistrib(uchar *buf, int len) { Forwtarg *tp; Udphdr *uh; static uchar outpkt[1500]; assert(len <= sizeof outpkt); memmove(outpkt, buf, len); uh = (Udphdr *)outpkt; for (tp = forwtarg; tp < forwtarg + currtarg; tp++) if (tp->fd > 0) { memmove(outpkt, tp->addr, sizeof tp->addr); hnputs(uh->rport, 53); /* dns port */ if (write(tp->fd, outpkt, len) != len) { close(tp->fd); tp->fd = -1; } } else if (tp->host && time(nil) - tp->lastdial > 60) { tp->lastdial = time(nil); tp->fd = udpport(mntpt); } }
void udpiput(struct Proto *udp, struct Ipifc *ifc, struct block *bp) { int len; Udp4hdr *uh4; Udp6hdr *uh6; struct conv *c; Udpcb *ucb; uint8_t raddr[IPaddrlen], laddr[IPaddrlen]; uint16_t rport, lport; Udppriv *upriv; struct Fs *f; int version; int ottl, oviclfl, olen; uint8_t *p; upriv = udp->priv; f = udp->f; upriv->ustats.udpInDatagrams++; uh4 = (Udp4hdr *) (bp->rp); version = ((uh4->vihl & 0xF0) == IP_VER6) ? V6 : V4; /* * Put back pseudo header for checksum * (remember old values for icmpnoconv()) */ switch (version) { case V4: ottl = uh4->Unused; uh4->Unused = 0; len = nhgets(uh4->udplen); olen = nhgets(uh4->udpplen); hnputs(uh4->udpplen, len); v4tov6(raddr, uh4->udpsrc); v4tov6(laddr, uh4->udpdst); lport = nhgets(uh4->udpdport); rport = nhgets(uh4->udpsport); if (!(bp->flag & Budpck) && (uh4->udpcksum[0] || uh4->udpcksum[1]) && ptclcsum(bp, UDP4_PHDR_OFF, len + UDP4_PHDR_SZ)) { upriv->ustats.udpInErrors++; netlog(f, Logudp, "udp: checksum error %I\n", raddr); printd("udp: checksum error %I\n", raddr); freeblist(bp); return; } uh4->Unused = ottl; hnputs(uh4->udpplen, olen); break; case V6: uh6 = (Udp6hdr *) (bp->rp); len = nhgets(uh6->udplen); oviclfl = nhgetl(uh6->viclfl); olen = nhgets(uh6->len); ottl = uh6->hoplimit; ipmove(raddr, uh6->udpsrc); ipmove(laddr, uh6->udpdst); lport = nhgets(uh6->udpdport); rport = nhgets(uh6->udpsport); memset(uh6, 0, 8); hnputl(uh6->viclfl, len); uh6->hoplimit = IP_UDPPROTO; if (ptclcsum(bp, UDP6_PHDR_OFF, len + UDP6_PHDR_SZ)) { upriv->ustats.udpInErrors++; netlog(f, Logudp, "udp: checksum error %I\n", raddr); printd("udp: checksum error %I\n", raddr); freeblist(bp); return; } hnputl(uh6->viclfl, oviclfl); hnputs(uh6->len, olen); uh6->nextheader = IP_UDPPROTO; uh6->hoplimit = ottl; break; default: panic("udpiput: version %d", version); return; /* to avoid a warning */ } qlock(&udp->qlock); c = iphtlook(&upriv->ht, raddr, rport, laddr, lport); if (c == NULL) { /* no converstation found */ upriv->ustats.udpNoPorts++; qunlock(&udp->qlock); netlog(f, Logudp, "udp: no conv %I!%d -> %I!%d\n", raddr, rport, laddr, lport); switch (version) { case V4: icmpnoconv(f, bp); break; case V6: icmphostunr(f, ifc, bp, icmp6_port_unreach, 0); break; default: panic("udpiput2: version %d", version); } freeblist(bp); return; } ucb = (Udpcb *) c->ptcl; if (c->state == Announced) { if (ucb->headers == 0) { /* create a new conversation */ if (ipforme(f, laddr) != Runi) { switch (version) { case V4: v4tov6(laddr, ifc->lifc->local); break; case V6: ipmove(laddr, ifc->lifc->local); break; default: panic("udpiput3: version %d", version); } } c = Fsnewcall(c, raddr, rport, laddr, lport, version); if (c == NULL) { qunlock(&udp->qlock); freeblist(bp); return; } iphtadd(&upriv->ht, c); ucb = (Udpcb *) c->ptcl; } } qlock(&c->qlock); qunlock(&udp->qlock); /* * Trim the packet down to data size */ len -= UDP_UDPHDR_SZ; switch (version) { case V4: bp = trimblock(bp, UDP4_IPHDR_SZ + UDP_UDPHDR_SZ, len); break; case V6: bp = trimblock(bp, UDP6_IPHDR_SZ + UDP_UDPHDR_SZ, len); break; default: bp = NULL; panic("udpiput4: version %d", version); } if (bp == NULL) { qunlock(&c->qlock); netlog(f, Logudp, "udp: len err %I.%d -> %I.%d\n", raddr, rport, laddr, lport); upriv->lenerr++; return; } netlog(f, Logudpmsg, "udp: %I.%d -> %I.%d l %d\n", raddr, rport, laddr, lport, len); switch (ucb->headers) { case 7: /* pass the src address */ bp = padblock(bp, UDP_USEAD7); p = bp->rp; ipmove(p, raddr); p += IPaddrlen; ipmove(p, laddr); p += IPaddrlen; ipmove(p, ifc->lifc->local); p += IPaddrlen; hnputs(p, rport); p += 2; hnputs(p, lport); break; case 6: /* pass the src address */ bp = padblock(bp, UDP_USEAD6); p = bp->rp; ipmove(p, raddr); p += IPaddrlen; ipmove(p, ipforme(f, laddr) == Runi ? laddr : ifc->lifc->local); p += IPaddrlen; hnputs(p, rport); p += 2; hnputs(p, lport); break; } if (bp->next) bp = concatblock(bp); if (qfull(c->rq)) { qunlock(&c->qlock); netlog(f, Logudp, "udp: qfull %I.%d -> %I.%d\n", raddr, rport, laddr, lport); freeblist(bp); return; } qpass(c->rq, bp); qunlock(&c->qlock); }
int main(int argc, char **argv) { char *addr, *p, *q, to[4]; char buf[2048]; int port, fd, nfd, one, len, n, tot; ulong ip; struct sockaddr_in sin; WSADATA wasdat; if(argc != 1 && argc != 2) { usage: fprintf(stderr, "usage: winplumb [tcp!ipaddr!port]\n"); ExitThread(1); } if(argc == 1) addr = "tcp!*!17890"; else addr = argv[1]; strcpy(buf, addr); p = strchr(buf, '!'); if(p == 0) goto usage; q = strchr(p+1, '!'); if(q == 0) goto usage; *p++ = 0; *q++ = 0; if(strcmp(buf, "tcp") != 0) goto usage; port = atoi(q); if(strcmp(p, "*") == 0) ip = 0; else ip = parseip(to, p); WSAStartup(MAKEWORD(1, 1), &wasdat); fd = socket(AF_INET, SOCK_STREAM, 0); if(fd < 0) { oserror(); fprintf(stderr, "socket: %s\n", errbuf); ExitThread(1); } one = 1; if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof one) != 0) { oserror(); fprintf(stderr, "setsockopt nodelay: %s\n", errbuf); } if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof one) != 0) { oserror(); fprintf(stderr, "setsockopt reuse: %s\n", errbuf); } memset(&sin, 0, sizeof sin); sin.sin_family = AF_INET; hnputs(&sin.sin_port, port); hnputl(&sin.sin_addr, ip); if(bind(fd, (struct sockaddr*)&sin, sizeof sin) < 0) { oserror(); fprintf(stderr, "bind: %s\n", errbuf); ExitThread(1); } if(listen(fd, 5) < 0) { oserror(); fprintf(stderr, "listen: %s\n", errbuf); ExitThread(1); } for(;;) { len = sizeof sin; nfd = accept(fd, (struct sockaddr*)&sin, &len); if(nfd < 0) { oserror(); fprintf(stderr, "accept: %s\n", errbuf); continue; } tot = 0; while(tot == 0 || buf[tot-1] != '\n') { n = recv(nfd, buf+tot, sizeof buf-tot, 0); if(n < 0) break; tot += n; } if(buf[tot-1] == '\n') { buf[tot-1] = 0; p = strchr(buf, ' '); if(p) *p++ = 0; ShellExecute(0, 0, buf, p, 0, SW_SHOWNORMAL); } closesocket(nfd); } }
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++; }
int pppoe(char *ether) { char buf[64]; uint8_t pkt[1520]; int dfd, p[2], n, sfd, sz, timeout; Pppoehdr *ph; ph = (Pppoehdr*)(pkt+EtherHdrSz); snprint(buf, sizeof buf, "%s!%d", ether, EtherPppoeDiscovery); if((dfd = dial(buf, nil, nil, nil)) < 0) sysfatal("dial %s: %r", buf); snprint(buf, sizeof buf, "%s!%d", ether, EtherPppoeSession); if((sfd = dial(buf, nil, nil, nil)) < 0) sysfatal("dial %s: %r", buf); for(timeout=250; timeout<16000; timeout*=2){ clearstate(); memset(pkt, 0, sizeof pkt); sz = padi(pkt); if(debug) dumppkt(pkt); if(sz < EtherMintu) sz = EtherMintu; ewrite(dfd, pkt, sz); if(pktread(timeout, dfd, pkt, sizeof pkt, wantoffer) < 0) continue; memset(pkt, 0, sizeof pkt); sz = padr(pkt); if(debug) dumppkt(pkt); if(sz < EtherMintu) sz = EtherMintu; ewrite(dfd, pkt, sz); if(pktread(timeout, dfd, pkt, sizeof pkt, wantsession) < 0) continue; break; } if(sessid < 0) sysfatal("could not establish session"); rfork(RFNOTEG); if(pipe(p) < 0) sysfatal("pipe: %r"); switch(fork()){ case -1: sysfatal("fork: %r"); default: break; case 0: close(p[1]); while((n = read(p[0], pkt+Hdr, sizeof pkt-Hdr)) > 0){ etherhdr(pkt, etherdst, EtherPppoeSession); pppoehdr(pkt+EtherHdrSz, 0x00, sessid); hnputs(pkt+Hdr-2, n); sz = Hdr+n; if(debug > 1){ dumppkt(pkt); hexdump(pkt, sz); } if(sz < EtherMintu) sz = EtherMintu; if(write(sfd, pkt, sz) < 0){ if(debug) fprint(2, "write to ether failed: %r"); _exits(nil); } } _exits(nil); } switch(fork()){ case -1: sysfatal("fork: %r"); default: break; case 0: close(p[1]); while((n = read(sfd, pkt, sizeof pkt)) > 0){ if(malformed(pkt, n, EtherPppoeSession) || ph->code != 0x00 || nhgets(ph->sessid) != sessid){ if(debug) fprint(2, "malformed session pkt: %r\n"); if(debug) dumppkt(pkt); continue; } if(write(p[0], pkt+Hdr, nhgets(ph->length)) < 0){ if(debug) fprint(2, "write to ppp failed: %r\n"); _exits(nil); } } _exits(nil); } close(p[0]); return p[1]; }