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