|
@@ -1,643 +0,0 @@
|
|
|
-#include "u.h"
|
|
|
-#include "../port/lib.h"
|
|
|
-#include "mem.h"
|
|
|
-#include "dat.h"
|
|
|
-#include "fns.h"
|
|
|
-#include "../port/error.h"
|
|
|
-
|
|
|
-#include "ip.h"
|
|
|
-#include "ipv6.h"
|
|
|
-
|
|
|
-
|
|
|
-#define DPRINT if(0)print
|
|
|
-
|
|
|
-enum
|
|
|
-{
|
|
|
- UDP_UDPHDR_SZ = 8,
|
|
|
-
|
|
|
- UDP4_PHDR_OFF = 8,
|
|
|
- UDP4_PHDR_SZ = 12,
|
|
|
- UDP4_IPHDR_SZ = 20,
|
|
|
- UDP6_IPHDR_SZ = 40,
|
|
|
- UDP6_PHDR_SZ = 40,
|
|
|
- UDP6_PHDR_OFF = 0,
|
|
|
-
|
|
|
- IP_UDPPROTO = 17,
|
|
|
- UDP_USEAD7 = 52,
|
|
|
- UDP_USEAD6 = 36,
|
|
|
-
|
|
|
- Udprxms = 200,
|
|
|
- Udptickms = 100,
|
|
|
- Udpmaxxmit = 10,
|
|
|
-};
|
|
|
-
|
|
|
-typedef struct Udp4hdr Udp4hdr;
|
|
|
-struct Udp4hdr
|
|
|
-{
|
|
|
- /* ip header */
|
|
|
- uchar vihl; /* Version and header length */
|
|
|
- uchar tos; /* Type of service */
|
|
|
- uchar length[2]; /* packet length */
|
|
|
- uchar id[2]; /* Identification */
|
|
|
- uchar frag[2]; /* Fragment information */
|
|
|
- uchar Unused;
|
|
|
- uchar udpproto; /* Protocol */
|
|
|
- uchar udpplen[2]; /* Header plus data length */
|
|
|
- uchar udpsrc[IPv4addrlen]; /* Ip source */
|
|
|
- uchar udpdst[IPv4addrlen]; /* Ip destination */
|
|
|
-
|
|
|
- /* udp header */
|
|
|
- uchar udpsport[2]; /* Source port */
|
|
|
- uchar udpdport[2]; /* Destination port */
|
|
|
- uchar udplen[2]; /* data length */
|
|
|
- uchar udpcksum[2]; /* Checksum */
|
|
|
-};
|
|
|
-
|
|
|
-typedef struct Udp6hdr Udp6hdr;
|
|
|
-struct Udp6hdr {
|
|
|
- uchar viclfl[4];
|
|
|
- uchar len[2];
|
|
|
- uchar nextheader;
|
|
|
- uchar hoplimit;
|
|
|
- uchar udpsrc[IPaddrlen];
|
|
|
- uchar udpdst[IPaddrlen];
|
|
|
-
|
|
|
- /* udp header */
|
|
|
- uchar udpsport[2]; /* Source port */
|
|
|
- uchar udpdport[2]; /* Destination port */
|
|
|
- uchar udplen[2]; /* data length */
|
|
|
- uchar udpcksum[2]; /* Checksum */
|
|
|
-};
|
|
|
-
|
|
|
-/* MIB II counters */
|
|
|
-typedef struct Udpstats Udpstats;
|
|
|
-struct Udpstats
|
|
|
-{
|
|
|
- ulong udpInDatagrams;
|
|
|
- ulong udpNoPorts;
|
|
|
- ulong udpInErrors;
|
|
|
- ulong udpOutDatagrams;
|
|
|
-};
|
|
|
-
|
|
|
-typedef struct Udppriv Udppriv;
|
|
|
-struct Udppriv
|
|
|
-{
|
|
|
- Ipht ht;
|
|
|
-
|
|
|
- /* MIB counters */
|
|
|
- Udpstats ustats;
|
|
|
-
|
|
|
- /* non-MIB stats */
|
|
|
- ulong csumerr; /* checksum errors */
|
|
|
- ulong lenerr; /* short packet */
|
|
|
-};
|
|
|
-
|
|
|
-void (*etherprofiler)(char *name, int qlen);
|
|
|
-void udpkick(void *x, Block *bp);
|
|
|
-
|
|
|
-/*
|
|
|
- * protocol specific part of Conv
|
|
|
- */
|
|
|
-typedef struct Udpcb Udpcb;
|
|
|
-struct Udpcb
|
|
|
-{
|
|
|
- QLock;
|
|
|
- uchar headers;
|
|
|
-};
|
|
|
-
|
|
|
-static char*
|
|
|
-udpconnect(Conv *c, char **argv, int argc)
|
|
|
-{
|
|
|
- char *e;
|
|
|
- Udppriv *upriv;
|
|
|
-
|
|
|
- upriv = c->p->priv;
|
|
|
- e = Fsstdconnect(c, argv, argc);
|
|
|
- Fsconnected(c, e);
|
|
|
- if(e != nil)
|
|
|
- return e;
|
|
|
-
|
|
|
- iphtadd(&upriv->ht, c);
|
|
|
- return nil;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static int
|
|
|
-udpstate(Conv *c, char *state, int n)
|
|
|
-{
|
|
|
- return snprint(state, n, "%s", c->inuse?"Open":"Closed");
|
|
|
-}
|
|
|
-
|
|
|
-static char*
|
|
|
-udpannounce(Conv *c, char** argv, int argc)
|
|
|
-{
|
|
|
- char *e;
|
|
|
- Udppriv *upriv;
|
|
|
-
|
|
|
- upriv = c->p->priv;
|
|
|
- e = Fsstdannounce(c, argv, argc);
|
|
|
- if(e != nil)
|
|
|
- return e;
|
|
|
- Fsconnected(c, nil);
|
|
|
- iphtadd(&upriv->ht, c);
|
|
|
-
|
|
|
- return nil;
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-udpcreate(Conv *c)
|
|
|
-{
|
|
|
- c->rq = qopen(128*1024, Qmsg, 0, 0);
|
|
|
- c->wq = qbypass(udpkick, c);
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-udpclose(Conv *c)
|
|
|
-{
|
|
|
- Udpcb *ucb;
|
|
|
- Udppriv *upriv;
|
|
|
-
|
|
|
- upriv = c->p->priv;
|
|
|
- iphtrem(&upriv->ht, c);
|
|
|
-
|
|
|
- c->state = 0;
|
|
|
- qclose(c->rq);
|
|
|
- qclose(c->wq);
|
|
|
- qclose(c->eq);
|
|
|
- ipmove(c->laddr, IPnoaddr);
|
|
|
- ipmove(c->raddr, IPnoaddr);
|
|
|
- c->lport = 0;
|
|
|
- c->rport = 0;
|
|
|
-
|
|
|
- ucb = (Udpcb*)c->ptcl;
|
|
|
- ucb->headers = 0;
|
|
|
-
|
|
|
- qunlock(c);
|
|
|
-}
|
|
|
-
|
|
|
-void
|
|
|
-udpkick(void *x, Block *bp)
|
|
|
-{
|
|
|
- Conv *c = x;
|
|
|
- Udp4hdr *uh4;
|
|
|
- Udp6hdr *uh6;
|
|
|
- ushort rport;
|
|
|
- uchar laddr[IPaddrlen], raddr[IPaddrlen];
|
|
|
- Udpcb *ucb;
|
|
|
- int dlen, ptcllen;
|
|
|
- Udppriv *upriv;
|
|
|
- Fs *f;
|
|
|
- int version;
|
|
|
- Conv *rc;
|
|
|
-
|
|
|
- upriv = c->p->priv;
|
|
|
- f = c->p->f;
|
|
|
-
|
|
|
- netlog(c->p->f, Logudp, "udp: kick\n");
|
|
|
- if(bp == nil)
|
|
|
- return;
|
|
|
-
|
|
|
- ucb = (Udpcb*)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;
|
|
|
- case 6:
|
|
|
- /* get user specified addresses */
|
|
|
- bp = pullupblock(bp, UDP_USEAD6);
|
|
|
- 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);
|
|
|
- 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 = 4;
|
|
|
- else
|
|
|
- version = 6;
|
|
|
- } else {
|
|
|
- if( (memcmp(c->raddr, v4prefix, IPv4off) == 0 &&
|
|
|
- memcmp(c->laddr, v4prefix, IPv4off) == 0)
|
|
|
- || ipcmp(c->raddr, IPnoaddr) == 0)
|
|
|
- version = 4;
|
|
|
- else
|
|
|
- version = 6;
|
|
|
- }
|
|
|
-
|
|
|
- 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 == nil)
|
|
|
- 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 = nil;
|
|
|
- } 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, dlen+UDP_UDPHDR_SZ+UDP4_PHDR_SZ));
|
|
|
- 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 == nil)
|
|
|
- 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 = nil;
|
|
|
- } 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++;
|
|
|
-}
|
|
|
-
|
|
|
-void
|
|
|
-udpiput(Proto *udp, Ipifc *ifc, Block *bp)
|
|
|
-{
|
|
|
- int len;
|
|
|
- Udp4hdr *uh4;
|
|
|
- Udp6hdr *uh6;
|
|
|
- Conv *c;
|
|
|
- Udpcb *ucb;
|
|
|
- uchar raddr[IPaddrlen], laddr[IPaddrlen];
|
|
|
- ushort rport, lport;
|
|
|
- Udppriv *upriv;
|
|
|
- Fs *f;
|
|
|
- int version;
|
|
|
- int ottl, oviclfl, olen;
|
|
|
- uchar *p;
|
|
|
-
|
|
|
- upriv = udp->priv;
|
|
|
- f = udp->f;
|
|
|
- upriv->ustats.udpInDatagrams++;
|
|
|
-
|
|
|
- uh4 = (Udp4hdr*)(bp->rp);
|
|
|
- version = ((uh4->vihl&0xF0)==IP_VER6) ? 6 : 4;
|
|
|
-
|
|
|
- /* 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(nhgets(uh4->udpcksum)) {
|
|
|
- if(ptclcsum(bp, UDP4_PHDR_OFF, len+UDP4_PHDR_SZ)) {
|
|
|
- upriv->ustats.udpInErrors++;
|
|
|
- netlog(f, Logudp, "udp: checksum error %I\n", raddr);
|
|
|
- DPRINT("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);
|
|
|
- DPRINT("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);
|
|
|
-
|
|
|
- c = iphtlook(&upriv->ht, raddr, rport, laddr, lport);
|
|
|
- if(c == nil){
|
|
|
- /* no converstation found */
|
|
|
- upriv->ustats.udpNoPorts++;
|
|
|
- qunlock(udp);
|
|
|
- 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 == nil){
|
|
|
- qunlock(udp);
|
|
|
- freeblist(bp);
|
|
|
- return;
|
|
|
- }
|
|
|
- iphtadd(&upriv->ht, c);
|
|
|
- ucb = (Udpcb*)c->ptcl;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- qlock(c);
|
|
|
- qunlock(udp);
|
|
|
-
|
|
|
- /*
|
|
|
- * 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 = nil;
|
|
|
- panic("udpiput4: version %d", version);
|
|
|
- }
|
|
|
- if(bp == nil){
|
|
|
- qunlock(c);
|
|
|
- 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);
|
|
|
- netlog(f, Logudp, "udp: qfull %I.%d -> %I.%d\n", raddr, rport,
|
|
|
- laddr, lport);
|
|
|
- freeblist(bp);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- qpass(c->rq, bp);
|
|
|
- qunlock(c);
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-char*
|
|
|
-udpctl(Conv *c, char **f, int n)
|
|
|
-{
|
|
|
- Udpcb *ucb;
|
|
|
-
|
|
|
- ucb = (Udpcb*)c->ptcl;
|
|
|
- if(n == 1){
|
|
|
- if(strcmp(f[0], "oldheaders") == 0){
|
|
|
- ucb->headers = 6;
|
|
|
- return nil;
|
|
|
- } else if(strcmp(f[0], "headers") == 0){
|
|
|
- ucb->headers = 7;
|
|
|
- return nil;
|
|
|
- }
|
|
|
- }
|
|
|
- return "unknown control request";
|
|
|
-}
|
|
|
-
|
|
|
-void
|
|
|
-udpadvise(Proto *udp, Block *bp, char *msg)
|
|
|
-{
|
|
|
- Udp4hdr *h4;
|
|
|
- Udp6hdr *h6;
|
|
|
- uchar source[IPaddrlen], dest[IPaddrlen];
|
|
|
- ushort psource, pdest;
|
|
|
- Conv *s, **p;
|
|
|
- int version;
|
|
|
-
|
|
|
- h4 = (Udp4hdr*)(bp->rp);
|
|
|
- version = ((h4->vihl&0xF0)==IP_VER6) ? 6 : 4;
|
|
|
-
|
|
|
- switch(version) {
|
|
|
- case V4:
|
|
|
- v4tov6(dest, h4->udpdst);
|
|
|
- v4tov6(source, h4->udpsrc);
|
|
|
- psource = nhgets(h4->udpsport);
|
|
|
- pdest = nhgets(h4->udpdport);
|
|
|
- break;
|
|
|
- case V6:
|
|
|
- h6 = (Udp6hdr*)(bp->rp);
|
|
|
- ipmove(dest, h6->udpdst);
|
|
|
- ipmove(source, h6->udpsrc);
|
|
|
- psource = nhgets(h6->udpsport);
|
|
|
- pdest = nhgets(h6->udpdport);
|
|
|
- break;
|
|
|
- default:
|
|
|
- panic("udpadvise: version %d", version);
|
|
|
- return; /* to avoid a warning */
|
|
|
- }
|
|
|
-
|
|
|
- /* Look for a connection */
|
|
|
- qlock(udp);
|
|
|
- for(p = udp->conv; *p; p++) {
|
|
|
- s = *p;
|
|
|
- if(s->rport == pdest)
|
|
|
- if(s->lport == psource)
|
|
|
- if(ipcmp(s->raddr, dest) == 0)
|
|
|
- if(ipcmp(s->laddr, source) == 0){
|
|
|
- if(s->ignoreadvice)
|
|
|
- break;
|
|
|
- qlock(s);
|
|
|
- qunlock(udp);
|
|
|
- qhangup(s->rq, msg);
|
|
|
- qhangup(s->wq, msg);
|
|
|
- qunlock(s);
|
|
|
- freeblist(bp);
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
- qunlock(udp);
|
|
|
- freeblist(bp);
|
|
|
-}
|
|
|
-
|
|
|
-int
|
|
|
-udpstats(Proto *udp, char *buf, int len)
|
|
|
-{
|
|
|
- Udppriv *upriv;
|
|
|
-
|
|
|
- upriv = udp->priv;
|
|
|
- return snprint(buf, len, "InDatagrams: %lud\nNoPorts: %lud\nInErrors: %lud\nOutDatagrams: %lud\n",
|
|
|
- upriv->ustats.udpInDatagrams,
|
|
|
- upriv->ustats.udpNoPorts,
|
|
|
- upriv->ustats.udpInErrors,
|
|
|
- upriv->ustats.udpOutDatagrams);
|
|
|
-}
|
|
|
-
|
|
|
-void
|
|
|
-udpinit(Fs *fs)
|
|
|
-{
|
|
|
- Proto *udp;
|
|
|
-
|
|
|
- udp = smalloc(sizeof(Proto));
|
|
|
- udp->priv = smalloc(sizeof(Udppriv));
|
|
|
- udp->name = "udp";
|
|
|
- udp->connect = udpconnect;
|
|
|
- udp->announce = udpannounce;
|
|
|
- udp->ctl = udpctl;
|
|
|
- udp->state = udpstate;
|
|
|
- udp->create = udpcreate;
|
|
|
- udp->close = udpclose;
|
|
|
- udp->rcv = udpiput;
|
|
|
- udp->advise = udpadvise;
|
|
|
- udp->stats = udpstats;
|
|
|
- udp->ipproto = IP_UDPPROTO;
|
|
|
- udp->nc = Nchans;
|
|
|
- udp->ptclsize = sizeof(Udpcb);
|
|
|
-
|
|
|
- Fsproto(fs, udp);
|
|
|
-}
|