|
|
1.1 root 1: #include "u.h"
2: #include "../port/lib.h"
3: #include "mem.h"
4: #include "dat.h"
5: #include "fns.h"
6: #include "../port/error.h"
7: #include "arp.h"
8: #include "../port/ipdat.h"
9:
10: #include "devtab.h"
11:
12: enum
13: {
14: Nrprotocol = 4, /* Number of protocols supported by this driver */
15: Nipsubdir = 4, /* Number of subdirectory entries per connection */
16: Nfrag = 32, /* Ip reassembly queue entries */
17: Nifc = 4, /* max interfaces */
18: };
19:
20: int udpsum = 1;
21: Ipifc *ipifc[Nrprotocol+1];
22: QLock ipalloc; /* Protocol port allocation lock */
23: Ipconv **tcpbase;
24:
25: Streamput udpstiput, udpstoput, tcpstiput, tcpstoput;
26: Streamput iliput, iloput, bsdiput, bsdoput;
27: Streamopen udpstopen, tcpstopen, ilopen, bsdopen;
28: Streamclose udpstclose, tcpstclose, ilclose, bsdclose;
29:
30: Qinfo tcpinfo = { tcpstiput, tcpstoput, tcpstopen, tcpstclose, "tcp", 0, 1 };
31: Qinfo udpinfo = { udpstiput, udpstoput, udpstopen, udpstclose, "udp" };
32: Qinfo ilinfo = { iliput, iloput, ilopen, ilclose, "il" };
33: Qinfo bsdinfo = { bsdiput, bsdoput, bsdopen, bsdclose, "bsd", 0, 1 };
34:
35: Qinfo *protocols[] = { &tcpinfo, &udpinfo, &ilinfo, 0 };
36:
37: void
38: ipinitifc(Ipifc *ifc, Qinfo *stproto)
39: {
40: ifc->conv = xalloc(Nipconv * sizeof(Ipconv*));
41: ifc->protop = stproto;
42: ifc->nconv = Nipconv;
43: ifc->devp = &ipconvinfo;
44: if(stproto != &udpinfo)
45: ifc->listen = iplisten;
46: ifc->clone = ipclonecon;
47: ifc->ninfo = 3;
48: ifc->info[0].name = "remote";
49: ifc->info[0].fill = ipremotefill;
50: ifc->info[1].name = "local";
51: ifc->info[1].fill = iplocalfill;
52: ifc->info[2].name = "status";
53: ifc->info[2].fill = ipstatusfill;
54: ifc->name = stproto->name;
55: }
56:
57: void
58: ipreset(void)
59: {
60: int i;
61:
62: for(i = 0; protocols[i]; i++) {
63: ipifc[i] = xalloc(sizeof(Ipifc));
64: ipinitifc(ipifc[i], protocols[i]);
65: newqinfo(protocols[i]);
66: }
67:
68: initfrag(Nfrag);
69: }
70:
71: void
72: ipinit(void)
73: {
74: }
75:
76: Chan *
77: ipattach(char *spec)
78: {
79: int i;
80: Chan *c;
81:
82: if(ipd[0].q == 0)
83: error("no ip multiplexor");
84:
85: for(i = 0; protocols[i]; i++) {
86: if(strcmp(spec, protocols[i]->name) == 0) {
87: c = devattach('I', spec);
88: c->dev = i;
89:
90: return (c);
91: }
92: }
93:
94: error(Enoproto);
95: return 0; /* not reached */
96: }
97:
98: Chan *
99: ipclone(Chan *c, Chan *nc)
100: {
101: return devclone(c, nc);
102: }
103:
104: int
105: ipwalk(Chan *c, char *name)
106: {
107: return netwalk(c, name, ipifc[c->dev]);
108: }
109:
110: void
111: ipstat(Chan *c, char *db)
112: {
113: netstat(c, db, ipifc[c->dev]);
114: }
115:
116: Chan *
117: ipopen(Chan *c, int omode)
118: {
119: return netopen(c, omode, ipifc[c->dev]);
120: }
121:
122: int
123: ipclonecon(Chan *c)
124: {
125: Ipconv *new;
126:
127: new = ipincoming(ipifc[c->dev], 0);
128: if(new == 0)
129: error(Enodev);
130: return new->id;
131: }
132:
133: /*
134: * create a new conversation structure if none exists for this conversation slot
135: */
136: Ipconv*
137: ipcreateconv(Ipifc *ifc, int id)
138: {
139: Ipconv **p;
140: Ipconv *new;
141:
142: p = &ifc->conv[id];
143: if(*p)
144: return *p;
145: qlock(ifc);
146: p = &ifc->conv[id];
147: if(*p){
148: qunlock(ifc);
149: return *p;
150: }
151: if(waserror()){
152: qunlock(ifc);
153: nexterror();
154: }
155: new = smalloc(sizeof(Ipconv));
156: new->ifc = ifc;
157: netadd(ifc, new, p - ifc->conv);
158: new->ref = 1;
159: *p = new;
160: qunlock(ifc);
161: poperror();
162: return new;
163: }
164:
165: /*
166: * allocate a conversation structure.
167: */
168: Ipconv*
169: ipincoming(Ipifc *ifc, Ipconv *from)
170: {
171: Ipconv *new;
172: Ipconv **p, **etab;
173:
174: /* look for an unused existing conversation */
175: etab = &ifc->conv[Nipconv];
176: for(p = ifc->conv; p < etab; p++) {
177: new = *p;
178: if(new == 0)
179: break;
180: if(new->ref == 0 && canqlock(new)) {
181: if(new->ref || ipconbusy(new)) {
182: qunlock(new);
183: continue;
184: }
185: if(from) /* copy ownership from listening channel */
186: netown(new, from->owner, 0);
187: else /* current user becomes owner */
188: netown(new, u->p->user, 0);
189:
190: new->ref = 1;
191: qunlock(new);
192: return new;
193: }
194: }
195:
196: /* create one */
197: qlock(ifc);
198: etab = &ifc->conv[Nipconv];
199: for(p = ifc->conv; ; p++){
200: if(p == etab){
201: qunlock(ifc);
202: return 0;
203: }
204: if(*p == 0)
205: break;
206: }
207: if(waserror()){
208: qunlock(ifc);
209: nexterror();
210: }
211: new = smalloc(sizeof(Ipconv));
212: new->ifc = ifc;
213: netadd(ifc, new, p - ifc->conv);
214: qlock(new);
215: *p = new;
216: qunlock(ifc);
217: poperror();
218: if(from) /* copy ownership from listening channel */
219: netown(new, from->owner, 0);
220: else /* current user becomes owner */
221: netown(new, u->p->user, 0);
222: new->ref = 1;
223: qunlock(new);
224: return new;
225: }
226:
227: void
228: ipcreate(Chan *c, char *name, int omode, ulong perm)
229: {
230: USED(c, name, omode, perm);
231: error(Eperm);
232: }
233:
234: void
235: ipremove(Chan *c)
236: {
237: USED(c);
238: error(Eperm);
239: }
240:
241: void
242: ipwstat(Chan *c, char *dp)
243: {
244: netwstat(c, dp, ipifc[c->dev]);
245: }
246:
247: void
248: ipclose(Chan *c)
249: {
250: if(c->stream)
251: streamclose(c);
252: }
253:
254: long
255: ipread(Chan *c, void *a, long n, ulong offset)
256: {
257: return netread(c, a, n, offset, ipifc[c->dev]);
258: }
259:
260: long
261: ipwrite(Chan *c, char *a, long n, ulong offset)
262: {
263: int m, backlog, type, priv;
264: char *field[5], *ctlarg[5], buf[256];
265: Port port;
266: Ipconv *cp;
267: uchar dst[4];
268:
269: USED(offset);
270: type = STREAMTYPE(c->qid.path);
271: if (type == Sdataqid)
272: return streamwrite(c, a, n, 0);
273:
274: if (type != Sctlqid)
275: error(Eperm);
276:
277: cp = ipcreateconv(ipifc[c->dev], STREAMID(c->qid.path));
278:
279: m = n;
280: if(m > sizeof(buf)-1)
281: m = sizeof(buf)-1;
282: strncpy(buf, a, m);
283: buf[m] = '\0';
284:
285: m = getfields(buf, field, 5, " ");
286: if(m < 1)
287: error(Ebadarg);
288:
289: if(strncmp(field[0], "connect", 7) == 0) {
290: if(ipconbusy(cp))
291: error(Enetbusy);
292:
293: if(m < 2)
294: error(Ebadarg);
295:
296: switch(getfields(field[1], ctlarg, 5, "!")) {
297: default:
298: error(Eneedservice);
299: case 2:
300: priv = 0;
301: break;
302: case 3:
303: if(strcmp(ctlarg[2], "r") != 0)
304: error(Eperm);
305: priv = 1;
306: break;
307: }
308: cp->dst = ipparse(ctlarg[0]);
309: hnputl(dst, cp->dst);
310: cp->src = ipgetsrc(dst);
311: cp->pdst = atoi(ctlarg[1]);
312:
313: /* If we have no local port assign one */
314: qlock(&ipalloc);
315: if(m == 3){
316: port = atoi(field[2]);
317: if(portused(ipifc[c->dev], cp->psrc)){
318: qunlock(&ipalloc);
319: error(Einuse);
320: }
321: cp->psrc = port;
322: }
323: if(cp->psrc == 0)
324: cp->psrc = nextport(ipifc[c->dev], priv);
325: qunlock(&ipalloc);
326:
327: if(cp->ifc->protop == &tcpinfo)
328: tcpstart(cp, TCP_ACTIVE, Streamhi, 0);
329: else if(cp->ifc->protop == &ilinfo)
330: ilstart(cp, IL_ACTIVE, 20);
331:
332: /*
333: * stupid hack for BSD port's 512, 513, & 514
334: * to make it harder for user to lie about his
335: * identity. -- presotto
336: */
337: switch(cp->pdst){
338: case 512:
339: case 513:
340: case 514:
341: pushq(c->stream, &bsdinfo);
342: break;
343: }
344:
345: memmove(cp->text, u->p->text, NAMELEN);
346: }
347: else if(strncmp(field[0], "disconnect", 10) == 0) {
348: if(cp->ifc->protop != &udpinfo)
349: error(Eperm);
350:
351: cp->dst = 0;
352: cp->pdst = 0;
353: }
354: else if(strncmp(field[0], "bind", 4) == 0) {
355: if(ipconbusy(cp))
356: error(Enetbusy);
357:
358: port = atoi(field[1]);
359:
360: if(port){
361: qlock(&ipalloc);
362: if(portused(ipifc[c->dev], port)) {
363: qunlock(&ipalloc);
364: error(Einuse);
365: }
366: cp->psrc = port;
367: qunlock(&ipalloc);
368: } else if(*field[1] != '*'){
369: qlock(&ipalloc);
370: cp->psrc = nextport(ipifc[c->dev], 0);
371: qunlock(&ipalloc);
372: } else
373: cp->psrc = 0;
374: }
375: else if(strncmp(field[0], "announce", 8) == 0) {
376: if(ipconbusy(cp))
377: error(Enetbusy);
378:
379: if(m != 2)
380: error(Ebadarg);
381:
382: port = atoi(field[1]);
383:
384: if(port){
385: qlock(&ipalloc);
386: if(portused(ipifc[c->dev], port)) {
387: qunlock(&ipalloc);
388: error(Einuse);
389: }
390: cp->psrc = port;
391: qunlock(&ipalloc);
392: } else if(*field[1] != '*'){
393: qlock(&ipalloc);
394: cp->psrc = nextport(ipifc[c->dev], 0);
395: qunlock(&ipalloc);
396: } else
397: cp->psrc = 0;
398:
399: if(cp->ifc->protop == &tcpinfo)
400: tcpstart(cp, TCP_PASSIVE, Streamhi, 0);
401: else if(cp->ifc->protop == &ilinfo)
402: ilstart(cp, IL_PASSIVE, 10);
403:
404: if(cp->backlog == 0)
405: cp->backlog = 3;
406:
407: memmove(cp->text, u->p->text, NAMELEN);
408: }
409: else if(strncmp(field[0], "backlog", 7) == 0) {
410: if(m != 2)
411: error(Ebadarg);
412: backlog = atoi(field[1]);
413: if(backlog == 0)
414: error(Ebadarg);
415: if(backlog > 5)
416: backlog = 5;
417: cp->backlog = backlog;
418: }
419: else if(strncmp(field[0], "headers", 7) == 0) {
420: cp->headers = 1; /* include addr/port in user packet */
421: }
422: else
423: return streamwrite(c, a, n, 0);
424:
425: return n;
426: }
427:
428: int
429: ipconbusy(Ipconv *cp)
430: {
431: if(cp->ifc->protop == &tcpinfo)
432: if(cp->tcpctl.state != Closed)
433: return 1;
434:
435: if(cp->ifc->protop == &ilinfo)
436: if(cp->ilctl.state != Ilclosed)
437: return 1;
438:
439: return 0;
440: }
441:
442: void
443: udpstiput(Queue *q, Block *bp)
444: {
445: PUTNEXT(q, bp);
446: }
447:
448: /*
449: * udprcvmsg - called by stip to multiplex udp ports onto conversations
450: */
451: void
452: udprcvmsg(Ipifc *ifc, Block *bp)
453: {
454: Ipconv *cp, **p, **etab;
455: Udphdr *uh;
456: Port dport, sport;
457: ushort sum, len;
458: Ipaddr addr;
459: Block *nbp;
460:
461: uh = (Udphdr *)(bp->rptr);
462:
463: /* Put back pseudo header for checksum */
464: uh->Unused = 0;
465: len = nhgets(uh->udplen);
466: hnputs(uh->udpplen, len);
467:
468: addr = nhgetl(uh->udpsrc);
469:
470: if(udpsum && nhgets(uh->udpcksum)) {
471: if(sum = ptcl_csum(bp, UDP_EHSIZE, len+UDP_PHDRSIZE)) {
472: print("udp: checksum error %x (%d.%d.%d.%d)\n",
473: sum, fmtaddr(addr));
474:
475: freeb(bp);
476: return;
477: }
478: }
479:
480: dport = nhgets(uh->udpdport);
481: sport = nhgets(uh->udpsport);
482:
483: /* Look for a conversation structure for this port */
484: etab = &ifc->conv[Nipconv];
485: for(p = ifc->conv; p < etab; p++) {
486: cp = *p;
487: if(cp == 0)
488: break;
489: if(cp->ref)
490: if(cp->psrc == dport)
491: if(cp->pdst == 0 || cp->pdst == sport) {
492: /* Trim the packet down to data size */
493: len = len - (UDP_HDRSIZE-UDP_PHDRSIZE);
494: bp = btrim(bp, UDP_EHSIZE+UDP_HDRSIZE, len);
495: if(bp == 0)
496: return;
497:
498: if(cp->headers){
499: /* pass the src address to the stream head */
500: nbp = allocb(Udphdrsize);
501: nbp->next = bp;
502: bp = nbp;
503: hnputl(bp->wptr, addr);
504: bp->wptr += 4;
505: hnputs(bp->wptr, sport);
506: bp->wptr += 2;
507: } else {
508: /* save the src address in the conversation struct */
509: cp->dst = addr;
510: cp->pdst = sport;
511: }
512: cp->src = 0;
513: PUTNEXT(cp->readq, bp);
514: return;
515: }
516: }
517:
518: freeb(bp);
519: }
520:
521: void
522: udpstoput(Queue *q, Block *bp)
523: {
524: Ipconv *cp;
525: Udphdr *uh;
526: int dlen, ptcllen, newlen;
527: Ipaddr addr;
528: Port port;
529: if(bp->type == M_CTL) {
530: PUTNEXT(q, bp);
531: return;
532: }
533:
534: cp = (Ipconv *)(q->ptr);
535: if(cp->psrc == 0){
536: freeb(bp);
537: error(Enoport);
538: }
539:
540: if(bp->type != M_DATA) {
541: freeb(bp);
542: error(Ebadctl);
543: }
544:
545: /* Only allow atomic udp writes to form datagrams */
546: if(!(bp->flags & S_DELIM)) {
547: freeb(bp);
548: error(Emsgsize);
549: }
550:
551: /*
552: * if we're in header mode, rip off the first 64 bytes as the
553: * destination. The destination is in ascii in the form
554: * %d.%d.%d.%d!%d
555: */
556: if(cp->headers){
557: /* get user specified addresses */
558: bp = pullup(bp, Udphdrsize);
559: if(bp == 0){
560: freeb(bp);
561: error(Emsgsize);
562: }
563: addr = nhgetl(bp->rptr);
564: bp->rptr += 4;
565: port = nhgets(bp->rptr);
566: bp->rptr += 2;
567: } else
568: addr = port = 0;
569:
570: /* Round packet up to even number of bytes and check we can
571: * send it
572: */
573: dlen = blen(bp);
574: if(dlen > UDP_DATMAX) {
575: freeb(bp);
576: error(Emsgsize);
577: }
578: newlen = dlen /*bround(bp, 1)*/;
579:
580: /* Make space to fit udp & ip & ethernet header */
581: bp = padb(bp, UDP_EHSIZE + UDP_HDRSIZE);
582:
583: uh = (Udphdr *)(bp->rptr);
584:
585: ptcllen = dlen + (UDP_HDRSIZE-UDP_PHDRSIZE);
586: uh->Unused = 0;
587: uh->udpproto = IP_UDPPROTO;
588: uh->frag[0] = 0;
589: uh->frag[1] = 0;
590: hnputs(uh->udpplen, ptcllen);
591: hnputs(uh->udpsport, cp->psrc);
592: if(cp->headers) {
593: hnputl(uh->udpdst, addr);
594: hnputs(uh->udpdport, port);
595: }
596: else {
597: hnputl(uh->udpdst, cp->dst);
598: hnputs(uh->udpdport, cp->pdst);
599: }
600: if(cp->src == 0)
601: cp->src = ipgetsrc(uh->udpdst);
602: hnputl(uh->udpsrc, cp->src);
603: hnputs(uh->udplen, ptcllen);
604: uh->udpcksum[0] = 0;
605: uh->udpcksum[1] = 0;
606:
607: hnputs(uh->udpcksum, ptcl_csum(bp, UDP_EHSIZE, newlen+UDP_HDRSIZE));
608: PUTNEXT(q, bp);
609: }
610:
611: void
612: udpstclose(Queue *q)
613: {
614: Ipconv *ipc;
615:
616: ipc = (Ipconv *)(q->ptr);
617:
618: ipc->headers = 0;
619: ipc->psrc = 0;
620: ipc->pdst = 0;
621: ipc->dst = 0;
622: }
623:
624: void
625: udpstopen(Queue *q, Stream *s)
626: {
627: Ipconv *ipc;
628:
629: ipc = ipcreateconv(ipifc[s->dev], s->id);
630: initipifc(ipifc[s->dev], IP_UDPPROTO, udprcvmsg);
631:
632: ipc->readq = RD(q);
633: RD(q)->ptr = (void *)ipc;
634: WR(q)->next->ptr = (void *)ipc->ifc;
635: WR(q)->ptr = (void *)ipc;
636: }
637:
638: void
639: tcpstiput(Queue *q, Block *bp)
640: {
641: PUTNEXT(q, bp);
642: }
643:
644: tcproominq(void *a)
645: {
646: return !((Tcpctl *)a)->sndfull;
647: }
648:
649: void
650: tcpstoput(Queue *q, Block *bp)
651: {
652: Ipconv *s;
653: Tcpctl *tcb;
654: Block *f;
655:
656: s = (Ipconv *)(q->ptr);
657: tcb = &s->tcpctl;
658:
659: if(bp->type == M_CTL) {
660: PUTNEXT(q, bp);
661: return;
662: }
663:
664: if(s->psrc == 0)
665: error(Enoport);
666:
667: /* Report asynchronous errors */
668: if(s->err)
669: error(s->err);
670:
671: switch(tcb->state) {
672: case Listen:
673: tcb->flags |= ACTIVE;
674: tcpsndsyn(tcb);
675: tcpsetstate(s, Syn_sent);
676:
677: /* No break */
678: case Syn_sent:
679: case Syn_received:
680: case Established:
681: /*
682: * Process flow control
683: */
684: if(tcb->sndfull){
685: qlock(&tcb->sndrlock);
686: if(waserror()) {
687: qunlock(&tcb->sndrlock);
688: freeb(bp);
689: nexterror();
690: }
691: sleep(&tcb->sndr, tcproominq, tcb);
692: poperror();
693: qunlock(&tcb->sndrlock);
694: }
695:
696: /*
697: * Push data
698: */
699: qlock(tcb);
700: if(waserror()) {
701: qunlock(tcb);
702: nexterror();
703: }
704:
705: /* make sure we don't queue onto something that just closed */
706: switch(tcb->state) {
707: case Syn_sent:
708: case Syn_received:
709: case Established:
710: break;
711: default:
712: freeb(bp);
713: error(Ehungup);
714: }
715:
716: tcb->sndcnt += blen(bp);
717: if(tcb->sndcnt > Streamhi)
718: tcb->sndfull = 1;
719: if(tcb->sndq == 0)
720: tcb->sndq = bp;
721: else {
722: for(f = tcb->sndq; f->next; f = f->next)
723: ;
724: f->next = bp;
725: }
726: tcprcvwin(s);
727: tcpoutput(s);
728: poperror();
729: qunlock(tcb);
730: break;
731:
732: case Close_wait:
733: default:
734: freeb(bp);
735: error(Ehungup);
736: }
737: }
738:
739: void
740: tcpstopen(Queue *q, Stream *s)
741: {
742: Ipconv *ipc;
743: Ipifc *ifc;
744: Tcpctl *tcb;
745: Block *bp;
746: static int tcpkprocs;
747:
748: /* Flow control and tcp timer processes */
749: if(tcpkprocs == 0) {
750: tcpkprocs = 1;
751: kproc("tcpack", tcpackproc, 0);
752: kproc("tcpflow", tcpflow, ipifc[s->dev]);
753:
754: }
755:
756: if(tcpbase == 0)
757: tcpbase = ipifc[s->dev]->conv;
758: ifc = ipifc[s->dev];
759: initipifc(ifc, IP_TCPPROTO, tcpinput);
760: ipc = ipcreateconv(ifc, s->id);
761:
762: ipc->readq = RD(q);
763: ipc->readq->rp = &tcpflowr;
764: ipc->err = 0;
765:
766: RD(q)->ptr = (void *)ipc;
767: WR(q)->ptr = (void *)ipc;
768:
769: /* pass any waiting data upstream */
770: tcb = &ipc->tcpctl;
771: qlock(tcb);
772: while(bp = getb(&tcb->rcvq))
773: PUTNEXT(ipc->readq, bp);
774: qunlock(tcb);
775: }
776:
777: void
778: ipremotefill(Chan *c, char *buf, int len)
779: {
780: Ipconv *cp;
781:
782: if(len < 24)
783: error(Ebadarg);
784: cp = ipcreateconv(ipifc[c->dev], STREAMID(c->qid.path));
785: sprint(buf, "%d.%d.%d.%d!%d\n", fmtaddr(cp->dst), cp->pdst);
786: }
787:
788: void
789: iplocalfill(Chan *c, char *buf, int len)
790: {
791: Ipconv *cp;
792:
793: if(len < 24)
794: error(Ebadarg);
795: cp = ipcreateconv(ipifc[c->dev], STREAMID(c->qid.path));
796: sprint(buf, "%d.%d.%d.%d!%d\n", fmtaddr(ipd[0].Myip[Myself]), cp->psrc);
797: }
798:
799: void
800: ipstatusfill(Chan *c, char *buf, int len)
801: {
802: Ipconv *cp;
803: int connection;
804:
805: if(len < 64)
806: error(Ebadarg);
807: connection = STREAMID(c->qid.path);
808: cp = ipcreateconv(ipifc[c->dev], connection);
809: if(cp->ifc->protop == &tcpinfo)
810: sprint(buf, "tcp/%d %d %s %s %s %d+%d\n", connection, cp->ref,
811: tcpstate[cp->tcpctl.state],
812: cp->tcpctl.flags & CLONE ? "listen" : "connect",
813: cp->text,
814: cp->tcpctl.srtt, cp->tcpctl.mdev);
815: else if(cp->ifc->protop == &ilinfo)
816: sprint(buf, "il/%d %d %s rtt %d ms %d csum\n", connection, cp->ref,
817: ilstate[cp->ilctl.state], cp->ilctl.rtt,
818: cp->ifc ? cp->ifc->chkerrs : 0);
819: else
820: sprint(buf, "%s/%d %d Datagram\n",
821: cp->ifc->protop->name, connection, cp->ref);
822: }
823:
824: int
825: iphavecon(Ipconv *s)
826: {
827: return s->curlog;
828: }
829:
830: int
831: iplisten(Chan *c)
832: {
833: Ipconv *s;
834: int connection;
835: Ipconv **p, **etab, *new;
836:
837: connection = STREAMID(c->qid.path);
838: s = ipcreateconv(ipifc[c->dev], connection);
839:
840: if(s->ifc->protop == &tcpinfo)
841: if(s->tcpctl.state != Listen)
842: error(Enolisten);
843:
844: if(s->ifc->protop == &ilinfo)
845: if(s->ilctl.state != Illistening)
846: error(Enolisten);
847:
848: for(;;) {
849: qlock(&s->listenq); /* single thread for the sleep */
850: if(waserror()) {
851: qunlock(&s->listenq);
852: nexterror();
853: }
854: sleep(&s->listenr, iphavecon, s);
855: poperror();
856: etab = &ipifc[c->dev]->conv[Nipconv];
857: for(p = ipifc[c->dev]->conv; p < etab; p++) {
858: new = *p;
859: if(new == 0)
860: break;
861: if(new->newcon == s) {
862: qlock(s);
863: s->curlog--;
864: qunlock(s);
865: new->newcon = 0;
866: qunlock(&s->listenq);
867: return new->id;
868: }
869: }
870: qunlock(&s->listenq);
871: print("iplisten: no newcon\n");
872: }
873: return -1; /* not reached */
874: }
875:
876: void
877: tcpstclose(Queue *q)
878: {
879: Ipconv *s, *new;
880: Ipconv **etab, **p;
881: Tcpctl *tcb;
882:
883: s = (Ipconv *)(q->ptr);
884: tcb = &s->tcpctl;
885:
886: /* Not interested in data anymore */
887: qlock(s);
888: s->readq = 0;
889: qunlock(s);
890:
891: switch(tcb->state){
892: case Listen:
893: /*
894: * reset any incoming calls to this listener
895: */
896: qlock(s);
897: s->backlog = 0;
898: s->curlog = 0;
899: etab = &tcpbase[Nipconv];
900: for(p = tcpbase; p < etab; p++){
901: new = *p;
902: if(new == 0)
903: break;
904: if(new->newcon == s){
905: new->newcon = 0;
906: tcpflushincoming(new);
907: new->ref = 0;
908: }
909: }
910: qunlock(s);
911:
912: qlock(tcb);
913: localclose(s, 0);
914: qunlock(tcb);
915: break;
916:
917: case Closed:
918: case Syn_sent:
919: qlock(tcb);
920: localclose(s, 0);
921: qunlock(tcb);
922: break;
923:
924: case Syn_received:
925: case Established:
926: tcb->sndcnt++;
927: tcb->snd.nxt++;
928: tcpsetstate(s, Finwait1);
929: goto output;
930:
931: case Close_wait:
932: tcb->sndcnt++;
933: tcb->snd.nxt++;
934: tcpsetstate(s, Last_ack);
935: output:
936: qlock(tcb);
937: if(waserror()) {
938: qunlock(tcb);
939: nexterror();
940: }
941: tcpoutput(s);
942: poperror();
943: qunlock(tcb);
944: break;
945: }
946: }
947:
948:
949: static short endian = 1;
950: static char* aendian = (char*)&endian;
951: #define LITTLE *aendian
952:
953: ushort
954: ptcl_bsum(uchar *addr, int len)
955: {
956: ulong losum, hisum, mdsum, x;
957: ulong t1, t2;
958:
959: losum = 0;
960: hisum = 0;
961: mdsum = 0;
962:
963: x = 0;
964: if((ulong)addr & 1) {
965: if(len) {
966: hisum += addr[0];
967: len--;
968: addr++;
969: }
970: x = 1;
971: }
972: while(len >= 16) {
973: t1 = *(ushort*)(addr+0);
974: t2 = *(ushort*)(addr+2); mdsum += t1;
975: t1 = *(ushort*)(addr+4); mdsum += t2;
976: t2 = *(ushort*)(addr+6); mdsum += t1;
977: t1 = *(ushort*)(addr+8); mdsum += t2;
978: t2 = *(ushort*)(addr+10); mdsum += t1;
979: t1 = *(ushort*)(addr+12); mdsum += t2;
980: t2 = *(ushort*)(addr+14); mdsum += t1;
981: mdsum += t2;
982: len -= 16;
983: addr += 16;
984: }
985: while(len >= 2) {
986: mdsum += *(ushort*)addr;
987: len -= 2;
988: addr += 2;
989: }
990: if(x) {
991: if(len)
992: losum += addr[0];
993: if(LITTLE)
994: losum += mdsum;
995: else
996: hisum += mdsum;
997: } else {
998: if(len)
999: hisum += addr[0];
1000: if(LITTLE)
1001: hisum += mdsum;
1002: else
1003: losum += mdsum;
1004: }
1005:
1006: losum += hisum >> 8;
1007: losum += (hisum & 0xff) << 8;
1008: while(hisum = losum>>16)
1009: losum = hisum + (losum & 0xffff);
1010:
1011: return losum & 0xffff;
1012: }
1013:
1014: ushort
1015: ptcl_csum(Block *bp, int offset, int len)
1016: {
1017: uchar *addr;
1018: ulong losum, hisum;
1019: ushort csum;
1020: int odd, blen, x;
1021:
1022: /* Correct to front of data area */
1023: while(bp && offset && offset >= BLEN(bp)) {
1024: offset -= BLEN(bp);
1025: bp = bp->next;
1026: }
1027: if(bp == 0)
1028: return 0;
1029:
1030: addr = bp->rptr + offset;
1031: blen = BLEN(bp) - offset;
1032:
1033: if(bp->next == 0)
1034: return ~ptcl_bsum(addr, MIN(len, blen)) & 0xffff;
1035:
1036: losum = 0;
1037: hisum = 0;
1038:
1039: odd = 0;
1040: while(len) {
1041: x = MIN(len, blen);
1042: csum = ptcl_bsum(addr, x);
1043: if(odd)
1044: hisum += csum;
1045: else
1046: losum += csum;
1047: odd = (odd+x) & 1;
1048: len -= x;
1049:
1050: bp = bp->next;
1051: if(bp == 0)
1052: break;
1053: blen = BLEN(bp);
1054: addr = bp->rptr;
1055: }
1056:
1057: losum += hisum>>8;
1058: losum += (hisum&0xff)<<8;
1059: while((csum = losum>>16) != 0)
1060: losum = csum + (losum & 0xffff);
1061:
1062: return ~losum & 0xffff;
1063: }
1064:
1065: Block *
1066: btrim(Block *bp, int offset, int len)
1067: {
1068: Block *nb, *startb;
1069: ulong l;
1070:
1071: if(blen(bp) < offset+len) {
1072: freeb(bp);
1073: return 0;
1074: }
1075:
1076: while((l = BLEN(bp)) < offset) {
1077: offset -= l;
1078: nb = bp->next;
1079: bp->next = 0;
1080: freeb(bp);
1081: bp = nb;
1082: }
1083:
1084: startb = bp;
1085: bp->rptr += offset;
1086:
1087: while((l = BLEN(bp)) < len) {
1088: len -= l;
1089: bp = bp->next;
1090: }
1091:
1092: bp->wptr -= (BLEN(bp) - len);
1093: bp->flags |= S_DELIM;
1094:
1095: if(bp->next) {
1096: freeb(bp->next);
1097: bp->next = 0;
1098: }
1099:
1100: return(startb);
1101: }
1102:
1103: Ipconv *
1104: portused(Ipifc *ifc, Port port)
1105: {
1106: Ipconv **p, **etab;
1107: Ipconv *cp;
1108:
1109: if(port == 0)
1110: return 0;
1111:
1112: etab = &ifc->conv[Nipconv];
1113: for(p = ifc->conv; p < etab; p++){
1114: cp = *p;
1115: if(cp == 0)
1116: break;
1117: if(cp->psrc == port)
1118: return cp;
1119: }
1120:
1121: return 0;
1122: }
1123:
1124: static Port lastport[2] = { PORTALLOC-1, PRIVPORTALLOC-1 };
1125:
1126: Port
1127: nextport(Ipifc *ifc, int priv)
1128: {
1129: Port base;
1130: Port max;
1131: Port *p;
1132: Port i;
1133:
1134: if(priv){
1135: base = PRIVPORTALLOC;
1136: max = UNPRIVPORTALLOC;
1137: p = &lastport[1];
1138: } else {
1139: base = PORTALLOC;
1140: max = PORTMAX;
1141: p = &lastport[0];
1142: }
1143:
1144: for(i = *p + 1; i < max; i++)
1145: if(!portused(ifc, i))
1146: return(*p = i);
1147: for(i = base ; i <= *p; i++)
1148: if(!portused(ifc, i))
1149: return(*p = i);
1150:
1151: return(0);
1152: }
1153:
1154: /* NEEDS HASHING ! */
1155:
1156: Ipconv*
1157: ip_conn(Ipifc *ifc, Port dst, Port src, Ipaddr dest)
1158: {
1159: Ipconv **p, *s, **etab;
1160:
1161: /* Look for a conversation structure for this port */
1162: etab = &ifc->conv[Nipconv];
1163: for(p = ifc->conv; p < etab; p++) {
1164: s = *p;
1165: if(s == 0)
1166: break;
1167: if(s->psrc == dst)
1168: if(s->pdst == src)
1169: if(s->dst == dest || dest == 0)
1170: return s;
1171: }
1172:
1173: return 0;
1174: }
1175:
1176: /*
1177: *
1178: * BSD authentication protocol, used on ports 512, 513, & 514.
1179: * This makes sure that a user can only write the REAL user id.
1180: *
1181: * q->ptr is number of nulls seen
1182: */
1183: void
1184: bsdopen(Queue *q, Stream *s)
1185: {
1186: USED(s);
1187: RD(q)->ptr = q;
1188: WR(q)->ptr = q;
1189: }
1190: void
1191: bsdclose(Queue *q)
1192: {
1193: Block *bp;
1194:
1195: bp = allocb(0);
1196: bp->type = M_HANGUP;
1197: PUTNEXT(q->other, bp);
1198: }
1199: void
1200: bsdiput(Queue *q, Block *bp)
1201: {
1202: PUTNEXT(q, bp);
1203: }
1204: void
1205: bsdoput(Queue *q, Block *bp)
1206: {
1207: uchar *luser;
1208: Block *nbp;
1209:
1210: /* just pass it on if we've done authentication */
1211: if(q->ptr == 0 || bp->type != M_DATA){
1212: PUTNEXT(q, bp);
1213: return;
1214: }
1215:
1216: /* collect into a single block */
1217: qlock(&q->rlock);
1218: if(q->first == 0)
1219: q->first = pullup(bp, blen(bp));
1220: else{
1221: nbp = q->first;
1222: nbp->next = bp;
1223: q->first = pullup(nbp, blen(nbp));
1224: }
1225: bp = q->first;
1226: if(bp == 0){
1227: qunlock(&q->rlock);
1228: bsdclose(q);
1229: return;
1230: }
1231:
1232: /* look for 2 nulls to indicate stderr port and local user */
1233: luser = memchr(bp->rptr, 0, BLEN(bp));
1234: if(luser == 0){
1235: qunlock(&q->rlock);
1236: return;
1237: }
1238: luser++;
1239: if(memchr(luser, 0, bp->wptr - luser) == 0){
1240: qunlock(&q->rlock);
1241: return;
1242: }
1243:
1244: /* if luser is a lie, hangup */
1245: if(memcmp(luser, u->p->user, strlen(u->p->user)+1) != 0)
1246: bsdclose(q);
1247:
1248: /* mark queue as authenticated and pass data to remote side */
1249: q->ptr = 0;
1250: q->first = 0;
1251: bp->flags |= S_DELIM;
1252: PUTNEXT(q, bp);
1253: qunlock(&q->rlock);
1254: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.