123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- #include <u.h>
- #include <libc.h>
- #include <ip.h>
- #include <thread.h>
- #include "netbios.h"
- static struct {
- int thread;
- QLock;
- int fd;
- } udp = { -1 };
- typedef struct Listen Listen;
- struct Listen {
- NbName to;
- int (*deliver)(void *magic, NbDgram *s);
- void *magic;
- Listen *next;
- };
- static struct {
- QLock;
- Listen *head;
- } listens;
- static void
- udplistener(void *)
- {
- //print("udplistener - starting\n");
- for (;;) {
- uchar msg[Udphdrsize + 576];
- int len = read(udp.fd, msg, sizeof(msg));
- if (len < 0)
- break;
- if (len >= nbudphdrsize) {
- NbDgram s;
- // Udphdr *uh;
- uchar *p;
- int n;
- // uh = (Udphdr*)msg;
- p = msg + nbudphdrsize;
- len -= nbudphdrsize;
- n = nbdgramconvM2S(&s, p, p + len);
- if (n) {
- switch (s.type) {
- case NbDgramError:
- print("nbdgramlisten: error: ip %I port %d code 0x%.2ux\n", s.srcip, s.srcport, s.error.code);
- break;
- case NbDgramDirectUnique:
- case NbDgramDirectGroup:
- case NbDgramBroadcast: {
- int delivered = 0;
- Listen **lp, *l;
- if ((s.flags & NbDgramMore) || s.datagram.offset != 0)
- break;
- if (!nbnameisany(s.datagram.dstname)
- && !nbnametablefind(s.datagram.dstname, 0)) {
- /* - only do this if a broadcast node, and can tell when packets are broadcast...
- s.flags &= 3;
- ipmove(s.srcip, nbglobals.myipaddr);
- s.srcport = NbDgramPort;
- s.type = NbDgramError;
- s.error.code = NbDgramErrorDestinationNameNotPresent;
- nbdgramsendto(uh->raddr, nhgets(uh->rport), &s);
- */
- break;
- }
- qlock(&listens);
- for (lp = &listens.head; (l = *lp) != nil;) {
- if (nbnameisany(l->to) || nbnameequal(l->to, s.datagram.dstname)) {
- switch ((*l->deliver)(l->magic, &s)) {
- case 0:
- delivered = 1;
- /* fall through */
- case -1:
- *lp = l->next;
- free(l);
- continue;
- default:
- delivered = 1;
- break;
- }
- }
- lp = &l->next;
- }
- qunlock(&listens);
- USED(delivered);
- }
- default:
- ;
- }
- }
- }
- }
- print("udplistener - exiting\n");
- qlock(&udp);
- udp.thread = -1;
- qunlock(&udp);
- }
- static char *
- startlistener(void)
- {
- qlock(&udp);
- if (udp.thread < 0) {
- char *e;
- e = nbudpannounce(NbDgramPort, &udp.fd);
- if (e) {
- qunlock(&udp);
- return e;
- }
- udp.thread = proccreate(udplistener, nil, 16384);
- }
- qunlock(&udp);
- return nil;
- }
- char *
- nbdgramlisten(NbName to, int (*deliver)(void *magic, NbDgram *s), void *magic)
- {
- Listen *l;
- char *e;
- nbnametablefind(to, 1);
- e = startlistener();
- if (e)
- return e;
- l = nbemalloc(sizeof(Listen));
- nbnamecpy(l->to, to);
- l->deliver = deliver;
- l->magic = magic;
- qlock(&listens);
- l->next = listens.head;
- listens.head = l;
- qunlock(&listens);
- return 0;
- }
- int
- nbdgramsendto(uchar *ipaddr, ushort port, NbDgram *s)
- {
- Udphdr *u;
- uchar 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 struct {
- Lock;
- ushort id;
- } id;
- static ushort
- nextdgramid(void)
- {
- ushort v;
- lock(&id);
- v = id.id++;
- unlock(&id);
- return v;
- }
- int
- nbdgramsend(NbDgramSendParameters *p, uchar *data, long datalen)
- {
- NbDgram s;
- uchar dstip[IPaddrlen];
- s.type = p->type;
- switch (p->type) {
- case NbDgramBroadcast:
- case NbDgramDirectGroup:
- ipmove(dstip, nbglobals.bcastaddr);
- break;
- case NbDgramDirectUnique:
- if (!nbnameresolve(p->to, dstip)) {
- werrstr("nbdgramsend: name resolution failed");
- return 0;
- }
- break;
- default:
- werrstr("nbdgramsend: illegal datagram type");
- return 0;
- }
- s.flags = NbDgramFirst;
- s.id = nextdgramid();
- ipmove(s.srcip, nbglobals.myipaddr);
- s.srcport = NbDgramPort;
- s.datagram.offset = 0;
- s.datagram.data = data;
- s.datagram.length = datalen;
- nbnamecpy(s.datagram.dstname, p->to);
- nbnamecpy(s.datagram.srcname, nbglobals.myname);
- return nbdgramsendto(dstip, NbDgramPort, &s);
- }
|