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 "../ip/ip.h" 8 9 enum 10 { 11 Qtopdir= 1, /* top level directory */ 12 Qtopbase, 13 Qarp= Qtopbase, 14 Qbootp, 15 Qndb, 16 Qiproute, 17 Qiprouter, 18 Qipselftab, 19 Qlog, 20 21 Qprotodir, /* directory for a protocol */ 22 Qprotobase, 23 Qclone= Qprotobase, 24 Qstats, 25 26 Qconvdir, /* directory for a conversation */ 27 Qconvbase, 28 Qctl= Qconvbase, 29 Qdata, 30 Qerr, 31 Qlisten, 32 Qlocal, 33 Qremote, 34 Qstatus, 35 Qsnoop, 36 37 Logtype= 5, 38 Masktype= (1<<Logtype)-1, 39 Logconv= 12, 40 Maskconv= (1<<Logconv)-1, 41 Shiftconv= Logtype, 42 Logproto= 8, 43 Maskproto= (1<<Logproto)-1, 44 Shiftproto= Logtype + Logconv, 45 46 Nfs= 32, 47 }; 48 #define TYPE(x) ( ((ulong)(x).path) & Masktype ) 49 #define CONV(x) ( (((ulong)(x).path) >> Shiftconv) & Maskconv ) 50 #define PROTO(x) ( (((ulong)(x).path) >> Shiftproto) & Maskproto ) 51 #define QID(p, c, y) ( ((p)<<(Shiftproto)) | ((c)<<Shiftconv) | (y) ) 52 53 static char network[] = "network"; 54 55 QLock fslock; 56 Fs *ipfs[Nfs]; /* attached fs's */ 57 Queue *qlog; 58 59 extern void nullmediumlink(void); 60 extern void pktmediumlink(void); 61 static long ndbwrite(Fs*, char*, ulong, int); 62 static void closeconv(Conv*); 63 64 static int 65 ip3gen(Chan *c, int i, Dir *dp) 66 { 67 Qid q; 68 Conv *cv; 69 char *p; 70 71 cv = ipfs[c->dev]->p[PROTO(c->qid)]->conv[CONV(c->qid)]; 72 if(cv->owner == nil) 73 kstrdup(&cv->owner, eve); 74 mkqid(&q, QID(PROTO(c->qid), CONV(c->qid), i), 0, QTFILE); 75 76 switch(i) { 77 default: 78 return -1; 79 case Qctl: 80 devdir(c, q, "ctl", 0, cv->owner, cv->perm, dp); 81 return 1; 82 case Qdata: 83 devdir(c, q, "data", qlen(cv->rq), cv->owner, cv->perm, dp); 84 return 1; 85 case Qerr: 86 devdir(c, q, "err", qlen(cv->eq), cv->owner, cv->perm, dp); 87 return 1; 88 case Qlisten: 89 devdir(c, q, "listen", 0, cv->owner, cv->perm, dp); 90 return 1; 91 case Qlocal: 92 p = "local"; 93 break; 94 case Qremote: 95 p = "remote"; 96 break; 97 case Qsnoop: 98 if(strcmp(cv->p->name, "ipifc") != 0) 99 return -1; 100 devdir(c, q, "snoop", qlen(cv->sq), cv->owner, 0400, dp); 101 return 1; 102 case Qstatus: 103 p = "status"; 104 break; 105 } 106 devdir(c, q, p, 0, cv->owner, 0444, dp); 107 return 1; 108 } 109 110 static int 111 ip2gen(Chan *c, int i, Dir *dp) 112 { 113 Qid q; 114 115 switch(i) { 116 case Qclone: 117 mkqid(&q, QID(PROTO(c->qid), 0, Qclone), 0, QTFILE); 118 devdir(c, q, "clone", 0, network, 0666, dp); 119 return 1; 120 case Qstats: 121 mkqid(&q, QID(PROTO(c->qid), 0, Qstats), 0, QTFILE); 122 devdir(c, q, "stats", 0, network, 0444, dp); 123 return 1; 124 } 125 return -1; 126 } 127 128 static int 129 ip1gen(Chan *c, int i, Dir *dp) 130 { 131 Qid q; 132 char *p; 133 int prot; 134 int len = 0; 135 Fs *f; 136 extern ulong kerndate; 137 138 f = ipfs[c->dev]; 139 140 prot = 0666; 141 mkqid(&q, QID(0, 0, i), 0, QTFILE); 142 switch(i) { 143 default: 144 return -1; 145 case Qarp: 146 p = "arp"; 147 break; 148 case Qbootp: 149 p = "bootp"; 150 if(bootp == nil) 151 return 0; 152 break; 153 case Qndb: 154 p = "ndb"; 155 len = strlen(f->ndb); 156 q.vers = f->ndbvers; 157 break; 158 case Qiproute: 159 p = "iproute"; 160 break; 161 case Qipselftab: 162 p = "ipselftab"; 163 prot = 0444; 164 break; 165 case Qiprouter: 166 p = "iprouter"; 167 break; 168 case Qlog: 169 p = "log"; 170 break; 171 } 172 devdir(c, q, p, len, network, prot, dp); 173 if(i == Qndb && f->ndbmtime > kerndate) 174 dp->mtime = f->ndbmtime; 175 return 1; 176 } 177 178 static int 179 ipgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp) 180 { 181 Qid q; 182 Conv *cv; 183 Fs *f; 184 185 f = ipfs[c->dev]; 186 187 switch(TYPE(c->qid)) { 188 case Qtopdir: 189 if(s == DEVDOTDOT){ 190 mkqid(&q, QID(0, 0, Qtopdir), 0, QTDIR); 191 sprint(up->genbuf, "#I%lud", c->dev); 192 devdir(c, q, up->genbuf, 0, network, 0555, dp); 193 return 1; 194 } 195 if(s < f->np) { 196 if(f->p[s]->connect == nil) 197 return 0; /* protocol with no user interface */ 198 mkqid(&q, QID(s, 0, Qprotodir), 0, QTDIR); 199 devdir(c, q, f->p[s]->name, 0, network, 0555, dp); 200 return 1; 201 } 202 s -= f->np; 203 return ip1gen(c, s+Qtopbase, dp); 204 case Qarp: 205 case Qbootp: 206 case Qndb: 207 case Qlog: 208 case Qiproute: 209 case Qiprouter: 210 case Qipselftab: 211 return ip1gen(c, TYPE(c->qid), dp); 212 case Qprotodir: 213 if(s == DEVDOTDOT){ 214 mkqid(&q, QID(0, 0, Qtopdir), 0, QTDIR); 215 sprint(up->genbuf, "#I%lud", c->dev); 216 devdir(c, q, up->genbuf, 0, network, 0555, dp); 217 return 1; 218 } 219 if(s < f->p[PROTO(c->qid)]->ac) { 220 cv = f->p[PROTO(c->qid)]->conv[s]; 221 sprint(up->genbuf, "%d", s); 222 mkqid(&q, QID(PROTO(c->qid), s, Qconvdir), 0, QTDIR); 223 devdir(c, q, up->genbuf, 0, cv->owner, 0555, dp); 224 return 1; 225 } 226 s -= f->p[PROTO(c->qid)]->ac; 227 return ip2gen(c, s+Qprotobase, dp); 228 case Qclone: 229 case Qstats: 230 return ip2gen(c, TYPE(c->qid), dp); 231 case Qconvdir: 232 if(s == DEVDOTDOT){ 233 s = PROTO(c->qid); 234 mkqid(&q, QID(s, 0, Qprotodir), 0, QTDIR); 235 devdir(c, q, f->p[s]->name, 0, network, 0555, dp); 236 return 1; 237 } 238 return ip3gen(c, s+Qconvbase, dp); 239 case Qctl: 240 case Qdata: 241 case Qerr: 242 case Qlisten: 243 case Qlocal: 244 case Qremote: 245 case Qstatus: 246 case Qsnoop: 247 return ip3gen(c, TYPE(c->qid), dp); 248 } 249 return -1; 250 } 251 252 static void 253 ipreset(void) 254 { 255 nullmediumlink(); 256 pktmediumlink(); 257 258 fmtinstall('i', eipfmt); 259 fmtinstall('I', eipfmt); 260 fmtinstall('E', eipfmt); 261 fmtinstall('V', eipfmt); 262 fmtinstall('M', eipfmt); 263 } 264 265 static Fs* 266 ipgetfs(int dev) 267 { 268 extern void (*ipprotoinit[])(Fs*); 269 Fs *f; 270 int i; 271 272 if(dev >= Nfs) 273 return nil; 274 275 qlock(&fslock); 276 if(ipfs[dev] == nil){ 277 f = smalloc(sizeof(Fs)); 278 ip_init(f); 279 arpinit(f); 280 netloginit(f); 281 for(i = 0; ipprotoinit[i]; i++) 282 ipprotoinit[i](f); 283 f->dev = dev; 284 ipfs[dev] = f; 285 } 286 qunlock(&fslock); 287 288 return ipfs[dev]; 289 } 290 291 IPaux* 292 newipaux(char *owner, char *tag) 293 { 294 IPaux *a; 295 int n; 296 297 a = smalloc(sizeof(*a)); 298 kstrdup(&a->owner, owner); 299 memset(a->tag, ' ', sizeof(a->tag)); 300 n = strlen(tag); 301 if(n > sizeof(a->tag)) 302 n = sizeof(a->tag); 303 memmove(a->tag, tag, n); 304 return a; 305 } 306 307 #define ATTACHER(c) (((IPaux*)((c)->aux))->owner) 308 309 static Chan* 310 ipattach(char* spec) 311 { 312 Chan *c; 313 int dev; 314 315 dev = atoi(spec); 316 if(dev >= Nfs) 317 error("bad specification"); 318 319 ipgetfs(dev); 320 c = devattach('I', spec); 321 mkqid(&c->qid, QID(0, 0, Qtopdir), 0, QTDIR); 322 c->dev = dev; 323 324 c->aux = newipaux(commonuser(), "none"); 325 326 return c; 327 } 328 329 static Walkqid* 330 ipwalk(Chan* c, Chan *nc, char **name, int nname) 331 { 332 IPaux *a = c->aux; 333 Walkqid* w; 334 335 w = devwalk(c, nc, name, nname, nil, 0, ipgen); 336 if(w != nil && w->clone != nil) 337 w->clone->aux = newipaux(a->owner, a->tag); 338 return w; 339 } 340 341 static int 342 ipstat(Chan* c, uchar* db, int n) 343 { 344 return devstat(c, db, n, nil, 0, ipgen); 345 } 346 347 static int 348 incoming(void* arg) 349 { 350 Conv *conv; 351 352 conv = arg; 353 return conv->incall != nil; 354 } 355 356 static int m2p[] = { 357 [OREAD] 4, 358 [OWRITE] 2, 359 [ORDWR] 6 360 }; 361 362 static Chan* 363 ipopen(Chan* c, int omode) 364 { 365 Conv *cv, *nc; 366 Proto *p; 367 int perm; 368 Fs *f; 369 370 perm = m2p[omode&3]; 371 372 f = ipfs[c->dev]; 373 374 switch(TYPE(c->qid)) { 375 default: 376 break; 377 case Qndb: 378 if(omode & (OWRITE|OTRUNC) && !iseve()) 379 error(Eperm); 380 if((omode & (OWRITE|OTRUNC)) == (OWRITE|OTRUNC)) 381 f->ndb[0] = 0; 382 break; 383 case Qlog: 384 netlogopen(f); 385 break; 386 case Qiprouter: 387 iprouteropen(f); 388 break; 389 case Qiproute: 390 break; 391 case Qtopdir: 392 case Qprotodir: 393 case Qconvdir: 394 case Qstatus: 395 case Qremote: 396 case Qlocal: 397 case Qstats: 398 case Qbootp: 399 case Qipselftab: 400 if(omode != OREAD) 401 error(Eperm); 402 break; 403 case Qsnoop: 404 if(omode != OREAD) 405 error(Eperm); 406 p = f->p[PROTO(c->qid)]; 407 cv = p->conv[CONV(c->qid)]; 408 if(strcmp(ATTACHER(c), cv->owner) != 0 && !iseve()) 409 error(Eperm); 410 incref(&cv->snoopers); 411 break; 412 case Qclone: 413 p = f->p[PROTO(c->qid)]; 414 qlock(p); 415 if(waserror()){ 416 qunlock(p); 417 nexterror(); 418 } 419 cv = Fsprotoclone(p, ATTACHER(c)); 420 qunlock(p); 421 poperror(); 422 if(cv == nil) { 423 error(Enodev); 424 break; 425 } 426 mkqid(&c->qid, QID(p->x, cv->x, Qctl), 0, QTFILE); 427 break; 428 case Qdata: 429 case Qctl: 430 case Qerr: 431 p = f->p[PROTO(c->qid)]; 432 qlock(p); 433 cv = p->conv[CONV(c->qid)]; 434 qlock(cv); 435 if(waserror()) { 436 qunlock(cv); 437 qunlock(p); 438 nexterror(); 439 } 440 if((perm & (cv->perm>>6)) != perm) { 441 if(strcmp(ATTACHER(c), cv->owner) != 0) 442 error(Eperm); 443 if((perm & cv->perm) != perm) 444 error(Eperm); 445 446 } 447 cv->inuse++; 448 if(cv->inuse == 1){ 449 kstrdup(&cv->owner, ATTACHER(c)); 450 cv->perm = 0660; 451 } 452 qunlock(cv); 453 qunlock(p); 454 poperror(); 455 break; 456 case Qlisten: 457 cv = f->p[PROTO(c->qid)]->conv[CONV(c->qid)]; 458 if((perm & (cv->perm>>6)) != perm) { 459 if(strcmp(ATTACHER(c), cv->owner) != 0) 460 error(Eperm); 461 if((perm & cv->perm) != perm) 462 error(Eperm); 463 464 } 465 466 if(cv->state != Announced) 467 error("not announced"); 468 469 if(waserror()){ 470 closeconv(cv); 471 nexterror(); 472 } 473 qlock(cv); 474 cv->inuse++; 475 qunlock(cv); 476 477 nc = nil; 478 while(nc == nil) { 479 /* give up if we got a hangup */ 480 if(qisclosed(cv->rq)) 481 error("listen hungup"); 482 483 qlock(&cv->listenq); 484 if(waserror()) { 485 qunlock(&cv->listenq); 486 nexterror(); 487 } 488 489 /* wait for a connect */ 490 sleep(&cv->listenr, incoming, cv); 491 492 qlock(cv); 493 nc = cv->incall; 494 if(nc != nil){ 495 cv->incall = nc->next; 496 mkqid(&c->qid, QID(PROTO(c->qid), nc->x, Qctl), 0, QTFILE); 497 kstrdup(&cv->owner, ATTACHER(c)); 498 } 499 qunlock(cv); 500 501 qunlock(&cv->listenq); 502 poperror(); 503 } 504 closeconv(cv); 505 poperror(); 506 break; 507 } 508 c->mode = openmode(omode); 509 c->flag |= COPEN; 510 c->offset = 0; 511 return c; 512 } 513 514 static int 515 ipwstat(Chan *c, uchar *dp, int n) 516 { 517 Dir *d; 518 Conv *cv; 519 Fs *f; 520 Proto *p; 521 522 f = ipfs[c->dev]; 523 switch(TYPE(c->qid)) { 524 default: 525 error(Eperm); 526 break; 527 case Qctl: 528 case Qdata: 529 break; 530 } 531 532 d = smalloc(sizeof(*d)+n); 533 if(waserror()){ 534 free(d); 535 nexterror(); 536 } 537 n = convM2D(dp, n, d, (char*)&d[1]); 538 if(n == 0) 539 error(Eshortstat); 540 p = f->p[PROTO(c->qid)]; 541 cv = p->conv[CONV(c->qid)]; 542 if(!iseve() && strcmp(ATTACHER(c), cv->owner) != 0) 543 error(Eperm); 544 if(!emptystr(d->uid)) 545 kstrdup(&cv->owner, d->uid); 546 if(d->mode != ~0UL) 547 cv->perm = d->mode & 0777; 548 poperror(); 549 free(d); 550 return n; 551 } 552 553 static void 554 closeconv(Conv *cv) 555 { 556 Conv *nc; 557 Ipmulti *mp; 558 559 qlock(cv); 560 561 if(--cv->inuse > 0) { 562 qunlock(cv); 563 return; 564 } 565 566 /* close all incoming calls since no listen will ever happen */ 567 for(nc = cv->incall; nc; nc = cv->incall){ 568 cv->incall = nc->next; 569 closeconv(nc); 570 } 571 cv->incall = nil; 572 573 kstrdup(&cv->owner, network); 574 cv->perm = 0660; 575 576 while((mp = cv->multi) != nil) 577 ipifcremmulti(cv, mp->ma, mp->ia); 578 579 cv->r = nil; 580 cv->rgen = 0; 581 cv->p->close(cv); 582 cv->state = Idle; 583 qunlock(cv); 584 } 585 586 static void 587 ipclose(Chan* c) 588 { 589 Fs *f; 590 591 f = ipfs[c->dev]; 592 switch(TYPE(c->qid)) { 593 default: 594 break; 595 case Qlog: 596 if(c->flag & COPEN) 597 netlogclose(f); 598 break; 599 case Qiprouter: 600 if(c->flag & COPEN) 601 iprouterclose(f); 602 break; 603 case Qdata: 604 case Qctl: 605 case Qerr: 606 if(c->flag & COPEN) 607 closeconv(f->p[PROTO(c->qid)]->conv[CONV(c->qid)]); 608 break; 609 case Qsnoop: 610 if(c->flag & COPEN) 611 decref(&f->p[PROTO(c->qid)]->conv[CONV(c->qid)]->snoopers); 612 break; 613 } 614 free(((IPaux*)c->aux)->owner); 615 free(c->aux); 616 } 617 618 enum 619 { 620 Statelen= 32*1024, 621 }; 622 623 static long 624 ipread(Chan *ch, void *a, long n, vlong off) 625 { 626 Conv *c; 627 Proto *x; 628 char *buf, *p; 629 long rv; 630 Fs *f; 631 ulong offset = off; 632 633 f = ipfs[ch->dev]; 634 635 p = a; 636 switch(TYPE(ch->qid)) { 637 default: 638 error(Eperm); 639 case Qtopdir: 640 case Qprotodir: 641 case Qconvdir: 642 return devdirread(ch, a, n, 0, 0, ipgen); 643 case Qarp: 644 return arpread(f->arp, a, offset, n); 645 case Qbootp: 646 return bootpread(a, offset, n); 647 case Qndb: 648 return readstr(offset, a, n, f->ndb); 649 case Qiproute: 650 return routeread(f, a, offset, n); 651 case Qiprouter: 652 return iprouterread(f, a, n); 653 case Qipselftab: 654 return ipselftabread(f, a, offset, n); 655 case Qlog: 656 return netlogread(f, a, offset, n); 657 case Qctl: 658 sprint(up->genbuf, "%lud", CONV(ch->qid)); 659 return readstr(offset, p, n, up->genbuf); 660 case Qremote: 661 buf = smalloc(Statelen); 662 x = f->p[PROTO(ch->qid)]; 663 c = x->conv[CONV(ch->qid)]; 664 if(x->remote == nil) { 665 sprint(buf, "%I!%d\n", c->raddr, c->rport); 666 } else { 667 (*x->remote)(c, buf, Statelen-2); 668 } 669 rv = readstr(offset, p, n, buf); 670 free(buf); 671 return rv; 672 case Qlocal: 673 buf = smalloc(Statelen); 674 x = f->p[PROTO(ch->qid)]; 675 c = x->conv[CONV(ch->qid)]; 676 if(x->local == nil) { 677 sprint(buf, "%I!%d\n", c->laddr, c->lport); 678 } else { 679 (*x->local)(c, buf, Statelen-2); 680 } 681 rv = readstr(offset, p, n, buf); 682 free(buf); 683 return rv; 684 case Qstatus: 685 buf = smalloc(Statelen); 686 x = f->p[PROTO(ch->qid)]; 687 c = x->conv[CONV(ch->qid)]; 688 (*x->state)(c, buf, Statelen-2); 689 rv = readstr(offset, p, n, buf); 690 free(buf); 691 return rv; 692 case Qdata: 693 c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)]; 694 return qread(c->rq, a, n); 695 case Qerr: 696 c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)]; 697 return qread(c->eq, a, n); 698 case Qsnoop: 699 c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)]; 700 return qread(c->sq, a, n); 701 case Qstats: 702 x = f->p[PROTO(ch->qid)]; 703 if(x->stats == nil) 704 error("stats not implemented"); 705 buf = smalloc(Statelen); 706 (*x->stats)(x, buf, Statelen); 707 rv = readstr(offset, p, n, buf); 708 free(buf); 709 return rv; 710 } 711 } 712 713 static Block* 714 ipbread(Chan* ch, long n, ulong offset) 715 { 716 Conv *c; 717 Proto *x; 718 Fs *f; 719 720 switch(TYPE(ch->qid)){ 721 case Qdata: 722 f = ipfs[ch->dev]; 723 x = f->p[PROTO(ch->qid)]; 724 c = x->conv[CONV(ch->qid)]; 725 return qbread(c->rq, n); 726 default: 727 return devbread(ch, n, offset); 728 } 729 } 730 731 /* 732 * set local address to be that of the ifc closest to remote address 733 */ 734 static void 735 setladdr(Conv* c) 736 { 737 findlocalip(c->p->f, c->laddr, c->raddr); 738 } 739 740 /* 741 * set a local port making sure the quad of raddr,rport,laddr,lport is unique 742 */ 743 static char* 744 setluniqueport(Conv* c, int lport) 745 { 746 Proto *p; 747 Conv *xp; 748 int x; 749 750 p = c->p; 751 752 qlock(p); 753 for(x = 0; x < p->nc; x++){ 754 xp = p->conv[x]; 755 if(xp == nil) 756 break; 757 if(xp == c) 758 continue; 759 if((xp->state == Connected || xp->state == Announced) 760 && xp->lport == lport 761 && xp->rport == c->rport 762 && ipcmp(xp->raddr, c->raddr) == 0 763 && ipcmp(xp->laddr, c->laddr) == 0){ 764 qunlock(p); 765 return "address in use"; 766 } 767 } 768 c->lport = lport; 769 qunlock(p); 770 return nil; 771 } 772 773 /* 774 * pick a local port and set it 775 */ 776 static void 777 setlport(Conv* c) 778 { 779 Proto *p; 780 ushort *pp; 781 int x, found; 782 783 p = c->p; 784 if(c->restricted) 785 pp = &p->nextrport; 786 else 787 pp = &p->nextport; 788 qlock(p); 789 for(;;(*pp)++){ 790 /* 791 * Fsproto initialises p->nextport to 0 and the restricted 792 * ports (p->nextrport) to 600. 793 * Restricted ports must lie between 600 and 1024. 794 * For the initial condition or if the unrestricted port number 795 * has wrapped round, select a random port between 5000 and 1<<15 796 * to start at. 797 */ 798 if(c->restricted){ 799 if(*pp >= 1024) 800 *pp = 600; 801 } 802 else while(*pp < 5000) 803 *pp = nrand(1<<15); 804 805 found = 0; 806 for(x = 0; x < p->nc; x++){ 807 if(p->conv[x] == nil) 808 break; 809 if(p->conv[x]->lport == *pp){ 810 found = 1; 811 break; 812 } 813 } 814 if(!found) 815 break; 816 } 817 c->lport = (*pp)++; 818 qunlock(p); 819 } 820 821 /* 822 * set a local address and port from a string of the form 823 * [address!]port[!r] 824 */ 825 static char* 826 setladdrport(Conv* c, char* str, int announcing) 827 { 828 char *p; 829 char *rv; 830 ushort lport; 831 uchar addr[IPaddrlen]; 832 833 rv = nil; 834 835 /* 836 * ignore restricted part if it exists. it's 837 * meaningless on local ports. 838 */ 839 p = strchr(str, '!'); 840 if(p != nil){ 841 *p++ = 0; 842 if(strcmp(p, "r") == 0) 843 p = nil; 844 } 845 846 c->lport = 0; 847 if(p == nil){ 848 if(announcing) 849 ipmove(c->laddr, IPnoaddr); 850 else 851 setladdr(c); 852 p = str; 853 } else { 854 if(strcmp(str, "*") == 0) 855 ipmove(c->laddr, IPnoaddr); 856 else { 857 parseip(addr, str); 858 if(ipforme(c->p->f, addr)) 859 ipmove(c->laddr, addr); 860 else 861 return "not a local IP address"; 862 } 863 } 864 865 /* one process can get all connections */ 866 if(announcing && strcmp(p, "*") == 0){ 867 if(!iseve()) 868 error(Eperm); 869 return setluniqueport(c, 0); 870 } 871 872 lport = atoi(p); 873 if(lport <= 0) 874 setlport(c); 875 else 876 rv = setluniqueport(c, lport); 877 return rv; 878 } 879 880 static char* 881 setraddrport(Conv* c, char* str) 882 { 883 char *p; 884 885 p = strchr(str, '!'); 886 if(p == nil) 887 return "malformed address"; 888 *p++ = 0; 889 parseip(c->raddr, str); 890 c->rport = atoi(p); 891 p = strchr(p, '!'); 892 if(p){ 893 if(strstr(p, "!r") != nil) 894 c->restricted = 1; 895 } 896 return nil; 897 } 898 899 /* 900 * called by protocol connect routine to set addresses 901 */ 902 char* 903 Fsstdconnect(Conv *c, char *argv[], int argc) 904 { 905 char *p; 906 907 switch(argc) { 908 default: 909 return "bad args to connect"; 910 case 2: 911 p = setraddrport(c, argv[1]); 912 if(p != nil) 913 return p; 914 setladdr(c); 915 setlport(c); 916 break; 917 case 3: 918 p = setraddrport(c, argv[1]); 919 if(p != nil) 920 return p; 921 p = setladdrport(c, argv[2], 0); 922 if(p != nil) 923 return p; 924 } 925 926 if((memcmp(c->raddr, v4prefix, IPv4off) == 0 && 927 memcmp(c->laddr, v4prefix, IPv4off) == 0) 928 || ipcmp(c->raddr, IPnoaddr) == 0) 929 c->ipversion = V4; 930 else 931 c->ipversion = V6; 932 933 return nil; 934 } 935 /* 936 * initiate connection and sleep till its set up 937 */ 938 static int 939 connected(void* a) 940 { 941 return ((Conv*)a)->state == Connected; 942 } 943 static void 944 connectctlmsg(Proto *x, Conv *c, Cmdbuf *cb) 945 { 946 char *p; 947 948 if(c->state != 0) 949 error(Econinuse); 950 c->state = Connecting; 951 c->cerr[0] = '\0'; 952 if(x->connect == nil) 953 error("connect not supported"); 954 p = x->connect(c, cb->f, cb->nf); 955 if(p != nil) 956 error(p); 957 958 qunlock(c); 959 if(waserror()){ 960 qlock(c); 961 nexterror(); 962 } 963 sleep(&c->cr, connected, c); 964 qlock(c); 965 poperror(); 966 967 if(c->cerr[0] != '\0') 968 error(c->cerr); 969 } 970 971 /* 972 * called by protocol announce routine to set addresses 973 */ 974 char* 975 Fsstdannounce(Conv* c, char* argv[], int argc) 976 { 977 memset(c->raddr, 0, sizeof(c->raddr)); 978 c->rport = 0; 979 switch(argc){ 980 default: 981 return "bad args to announce"; 982 case 2: 983 return setladdrport(c, argv[1], 1); 984 } 985 } 986 987 /* 988 * initiate announcement and sleep till its set up 989 */ 990 static int 991 announced(void* a) 992 { 993 return ((Conv*)a)->state == Announced; 994 } 995 static void 996 announcectlmsg(Proto *x, Conv *c, Cmdbuf *cb) 997 { 998 char *p; 999 1000 if(c->state != 0) 1001 error(Econinuse); 1002 c->state = Announcing; 1003 c->cerr[0] = '\0'; 1004 if(x->announce == nil) 1005 error("announce not supported"); 1006 p = x->announce(c, cb->f, cb->nf); 1007 if(p != nil) 1008 error(p); 1009 1010 qunlock(c); 1011 if(waserror()){ 1012 qlock(c); 1013 nexterror(); 1014 } 1015 sleep(&c->cr, announced, c); 1016 qlock(c); 1017 poperror(); 1018 1019 if(c->cerr[0] != '\0') 1020 error(c->cerr); 1021 } 1022 1023 /* 1024 * called by protocol bind routine to set addresses 1025 */ 1026 char* 1027 Fsstdbind(Conv* c, char* argv[], int argc) 1028 { 1029 switch(argc){ 1030 default: 1031 return "bad args to bind"; 1032 case 2: 1033 return setladdrport(c, argv[1], 0); 1034 } 1035 } 1036 1037 static void 1038 bindctlmsg(Proto *x, Conv *c, Cmdbuf *cb) 1039 { 1040 char *p; 1041 1042 if(x->bind == nil) 1043 p = Fsstdbind(c, cb->f, cb->nf); 1044 else 1045 p = x->bind(c, cb->f, cb->nf); 1046 if(p != nil) 1047 error(p); 1048 } 1049 1050 static void 1051 tosctlmsg(Conv *c, Cmdbuf *cb) 1052 { 1053 if(cb->nf < 2) 1054 c->tos = 0; 1055 else 1056 c->tos = atoi(cb->f[1]); 1057 } 1058 1059 static void 1060 ttlctlmsg(Conv *c, Cmdbuf *cb) 1061 { 1062 if(cb->nf < 2) 1063 c->ttl = MAXTTL; 1064 else 1065 c->ttl = atoi(cb->f[1]); 1066 } 1067 1068 static long 1069 ipwrite(Chan* ch, void *v, long n, vlong off) 1070 { 1071 Conv *c; 1072 Proto *x; 1073 char *p; 1074 Cmdbuf *cb; 1075 uchar ia[IPaddrlen], ma[IPaddrlen]; 1076 Fs *f; 1077 char *a; 1078 1079 a = v; 1080 f = ipfs[ch->dev]; 1081 1082 switch(TYPE(ch->qid)){ 1083 default: 1084 error(Eperm); 1085 case Qdata: 1086 x = f->p[PROTO(ch->qid)]; 1087 c = x->conv[CONV(ch->qid)]; 1088 1089 if(c->wq == nil) 1090 error(Eperm); 1091 1092 qwrite(c->wq, a, n); 1093 break; 1094 case Qarp: 1095 return arpwrite(f, a, n); 1096 case Qiproute: 1097 return routewrite(f, ch, a, n); 1098 case Qlog: 1099 netlogctl(f, a, n); 1100 return n; 1101 case Qndb: 1102 return ndbwrite(f, a, off, n); 1103 case Qctl: 1104 x = f->p[PROTO(ch->qid)]; 1105 c = x->conv[CONV(ch->qid)]; 1106 cb = parsecmd(a, n); 1107 1108 qlock(c); 1109 if(waserror()) { 1110 qunlock(c); 1111 free(cb); 1112 nexterror(); 1113 } 1114 if(cb->nf < 1) 1115 error("short control request"); 1116 if(strcmp(cb->f[0], "connect") == 0) 1117 connectctlmsg(x, c, cb); 1118 else if(strcmp(cb->f[0], "announce") == 0) 1119 announcectlmsg(x, c, cb); 1120 else if(strcmp(cb->f[0], "bind") == 0) 1121 bindctlmsg(x, c, cb); 1122 else if(strcmp(cb->f[0], "ttl") == 0) 1123 ttlctlmsg(c, cb); 1124 else if(strcmp(cb->f[0], "tos") == 0) 1125 tosctlmsg(c, cb); 1126 else if(strcmp(cb->f[0], "ignoreadvice") == 0) 1127 c->ignoreadvice = 1; 1128 else if(strcmp(cb->f[0], "addmulti") == 0){ 1129 if(cb->nf < 2) 1130 error("addmulti needs interface address"); 1131 if(cb->nf == 2){ 1132 if(!ipismulticast(c->raddr)) 1133 error("addmulti for a non multicast address"); 1134 parseip(ia, cb->f[1]); 1135 ipifcaddmulti(c, c->raddr, ia); 1136 } else { 1137 parseip(ma, cb->f[2]); 1138 if(!ipismulticast(ma)) 1139 error("addmulti for a non multicast address"); 1140 parseip(ia, cb->f[1]); 1141 ipifcaddmulti(c, ma, ia); 1142 } 1143 } else if(strcmp(cb->f[0], "remmulti") == 0){ 1144 if(cb->nf < 2) 1145 error("remmulti needs interface address"); 1146 if(!ipismulticast(c->raddr)) 1147 error("remmulti for a non multicast address"); 1148 parseip(ia, cb->f[1]); 1149 ipifcremmulti(c, c->raddr, ia); 1150 } else if(x->ctl != nil) { 1151 p = x->ctl(c, cb->f, cb->nf); 1152 if(p != nil) 1153 error(p); 1154 } else 1155 error("unknown control request"); 1156 qunlock(c); 1157 free(cb); 1158 poperror(); 1159 } 1160 return n; 1161 } 1162 1163 static long 1164 ipbwrite(Chan* ch, Block* bp, ulong offset) 1165 { 1166 Conv *c; 1167 Proto *x; 1168 Fs *f; 1169 int n; 1170 1171 switch(TYPE(ch->qid)){ 1172 case Qdata: 1173 f = ipfs[ch->dev]; 1174 x = f->p[PROTO(ch->qid)]; 1175 c = x->conv[CONV(ch->qid)]; 1176 1177 if(c->wq == nil) 1178 error(Eperm); 1179 1180 if(bp->next) 1181 bp = concatblock(bp); 1182 n = BLEN(bp); 1183 qbwrite(c->wq, bp); 1184 return n; 1185 default: 1186 return devbwrite(ch, bp, offset); 1187 } 1188 } 1189 1190 Dev ipdevtab = { 1191 'I', 1192 "ip", 1193 1194 ipreset, 1195 devinit, 1196 devshutdown, 1197 ipattach, 1198 ipwalk, 1199 ipstat, 1200 ipopen, 1201 devcreate, 1202 ipclose, 1203 ipread, 1204 ipbread, 1205 ipwrite, 1206 ipbwrite, 1207 devremove, 1208 ipwstat, 1209 }; 1210 1211 int 1212 Fsproto(Fs *f, Proto *p) 1213 { 1214 if(f->np >= Maxproto) 1215 return -1; 1216 1217 p->f = f; 1218 1219 if(p->ipproto > 0){ 1220 if(f->t2p[p->ipproto] != nil) 1221 return -1; 1222 f->t2p[p->ipproto] = p; 1223 } 1224 1225 p->qid.type = QTDIR; 1226 p->qid.path = QID(f->np, 0, Qprotodir); 1227 p->conv = malloc(sizeof(Conv*)*(p->nc+1)); 1228 if(p->conv == nil) 1229 panic("Fsproto"); 1230 1231 p->x = f->np; 1232 p->nextport = 0; 1233 p->nextrport = 600; 1234 f->p[f->np++] = p; 1235 1236 return 0; 1237 } 1238 1239 /* 1240 * return true if this protocol is 1241 * built in 1242 */ 1243 int 1244 Fsbuiltinproto(Fs* f, uchar proto) 1245 { 1246 return f->t2p[proto] != nil; 1247 } 1248 1249 /* 1250 * called with protocol locked 1251 */ 1252 Conv* 1253 Fsprotoclone(Proto *p, char *user) 1254 { 1255 Conv *c, **pp, **ep; 1256 1257 retry: 1258 c = nil; 1259 ep = &p->conv[p->nc]; 1260 for(pp = p->conv; pp < ep; pp++) { 1261 c = *pp; 1262 if(c == nil){ 1263 c = malloc(sizeof(Conv)); 1264 if(c == nil) 1265 error(Enomem); 1266 qlock(c); 1267 c->p = p; 1268 c->x = pp - p->conv; 1269 if(p->ptclsize != 0){ 1270 c->ptcl = malloc(p->ptclsize); 1271 if(c->ptcl == nil) { 1272 free(c); 1273 error(Enomem); 1274 } 1275 } 1276 *pp = c; 1277 p->ac++; 1278 c->eq = qopen(1024, Qmsg, 0, 0); 1279 (*p->create)(c); 1280 break; 1281 } 1282 if(canqlock(c)){ 1283 /* 1284 * make sure both processes and protocol 1285 * are done with this Conv 1286 */ 1287 if(c->inuse == 0 && (p->inuse == nil || (*p->inuse)(c) == 0)) 1288 break; 1289 1290 qunlock(c); 1291 } 1292 } 1293 if(pp >= ep) { 1294 if(p->gc != nil && (*p->gc)(p)) 1295 goto retry; 1296 return nil; 1297 } 1298 1299 c->inuse = 1; 1300 kstrdup(&c->owner, user); 1301 c->perm = 0660; 1302 c->state = Idle; 1303 ipmove(c->laddr, IPnoaddr); 1304 ipmove(c->raddr, IPnoaddr); 1305 c->r = nil; 1306 c->rgen = 0; 1307 c->lport = 0; 1308 c->rport = 0; 1309 c->restricted = 0; 1310 c->ttl = MAXTTL; 1311 c->tos = DFLTTOS; 1312 qreopen(c->rq); 1313 qreopen(c->wq); 1314 qreopen(c->eq); 1315 1316 qunlock(c); 1317 return c; 1318 } 1319 1320 int 1321 Fsconnected(Conv* c, char* msg) 1322 { 1323 if(msg != nil && *msg != '\0') 1324 kstrcpy(c->cerr, msg, sizeof(c->cerr)); 1325 1326 switch(c->state){ 1327 1328 case Announcing: 1329 c->state = Announced; 1330 break; 1331 1332 case Connecting: 1333 c->state = Connected; 1334 break; 1335 } 1336 1337 wakeup(&c->cr); 1338 return 0; 1339 } 1340 1341 Proto* 1342 Fsrcvpcol(Fs* f, uchar proto) 1343 { 1344 if(f->ipmux) 1345 return f->ipmux; 1346 else 1347 return f->t2p[proto]; 1348 } 1349 1350 Proto* 1351 Fsrcvpcolx(Fs *f, uchar proto) 1352 { 1353 return f->t2p[proto]; 1354 } 1355 1356 /* 1357 * called with protocol locked 1358 */ 1359 Conv* 1360 Fsnewcall(Conv *c, uchar *raddr, ushort rport, uchar *laddr, ushort lport, uchar version) 1361 { 1362 Conv *nc; 1363 Conv **l; 1364 int i; 1365 1366 qlock(c); 1367 i = 0; 1368 for(l = &c->incall; *l; l = &(*l)->next) 1369 i++; 1370 if(i >= Maxincall) { 1371 qunlock(c); 1372 return nil; 1373 } 1374 1375 /* find a free conversation */ 1376 nc = Fsprotoclone(c->p, network); 1377 if(nc == nil) { 1378 qunlock(c); 1379 return nil; 1380 } 1381 ipmove(nc->raddr, raddr); 1382 nc->rport = rport; 1383 ipmove(nc->laddr, laddr); 1384 nc->lport = lport; 1385 nc->next = nil; 1386 *l = nc; 1387 nc->state = Connected; 1388 nc->ipversion = version; 1389 1390 qunlock(c); 1391 1392 wakeup(&c->listenr); 1393 1394 return nc; 1395 } 1396 1397 static long 1398 ndbwrite(Fs *f, char *a, ulong off, int n) 1399 { 1400 if(off > strlen(f->ndb)) 1401 error(Eio); 1402 if(off+n >= sizeof(f->ndb)-1) 1403 error(Eio); 1404 memmove(f->ndb+off, a, n); 1405 f->ndb[off+n] = 0; 1406 f->ndbvers++; 1407 f->ndbmtime = seconds(); 1408 return n; 1409 } 1410 1411 ulong 1412 scalednconv(void) 1413 { 1414 if(conf.npage*BY2PG >= 128*MB) 1415 return Nchans*4; 1416 return Nchans; 1417 } 1418