|
|
1.1 ! root 1: #include <sys/types.h> ! 2: #include <stdio.h> ! 3: #include <signal.h> ! 4: #include <errno.h> ! 5: #include <ipc.h> ! 6: #include <sys/filio.h> ! 7: #include <sys/inio.h> ! 8: #include <sys/inet/tcp_user.h> ! 9: #include <sys/inet/tcp_timer.h> ! 10: #include <sys/inet/tcp_var.h> ! 11: #include <libc.h> ! 12: #include <ctype.h> ! 13: #include "defs.h" ! 14: ! 15: #define CSPORT 1 ! 16: ! 17: #define CALLIN 0 ! 18: #define CALLOUT 1 ! 19: #define ANNOUNCE 2 ! 20: #define CALLINCS 3 ! 21: ! 22: /* imported */ ! 23: extern char *in_ntoa(); ! 24: extern in_addr in_address(); ! 25: extern int tcp_connect(); ! 26: extern int tcp_accept(); ! 27: extern int tcp_listen(); ! 28: extern char *in_host(); ! 29: extern in_addr in_aton(); ! 30: extern int rmesg_ld; ! 31: extern char *mydomain; ! 32: ! 33: Qset *domainorder(); ! 34: ! 35: /* dial a service on the internet - try first via cs, then direct */ ! 36: int ! 37: net_dial(ip) ! 38: ipcinfo *ip; ! 39: { ! 40: char *service; ! 41: int lport, fport; ! 42: int i, n, fd; ! 43: char *fields[16]; ! 44: Qset *sp, *tsp; ! 45: Qtuple *tp; ! 46: int tries; ! 47: char *dom, *in, *firstdom; ! 48: char dname[256]; ! 49: int gooddom; ! 50: ! 51: lport = 0; ! 52: tries = 0; ! 53: ! 54: /* break parameter list */ ! 55: n = breakparams(ip, fields, 16); ! 56: for(i=0; i<n; i++){ ! 57: if(strncmp(fields[i], "port=", 5)==0){ ! 58: lport=atoi(fields[i]+5); ! 59: if(lport<1024 && ip->uid!=0) ! 60: return ABORT(ENOENT, "illegal port", NULLINFO); ! 61: break; ! 62: } ! 63: } ! 64: ! 65: /* get the service */ ! 66: service = strchr(ip->name, '!'); ! 67: if (service != NULL) ! 68: *service++ = '\0'; ! 69: else ! 70: return ABORT(ENOENT, "unassigned service", NULLINFO); ! 71: fport = fstotcp(service); ! 72: ! 73: /* look up the system */ ! 74: strcpy(dname, ip->name); ! 75: strcat(dname, ",dom"); ! 76: sp = qset(dname, (char *)NULL); ! 77: if (sp==NULL) { ! 78: sp = qset(ip->name, (char *)NULL); ! 79: if(sp==NULL){ ! 80: /* no such system - assume we have an ip number */ ! 81: if(isdigit(*ip->name)) ! 82: return dialip(ip->name, lport, fport, fields, n, ! 83: ip, service); ! 84: else ! 85: return ABORT(ENOENT, "unassigned destination", ! 86: NULLINFO); ! 87: } ! 88: } ! 89: ! 90: /* call each INET address in succession. If a domain name is ! 91: * encountered, try no entry of another doain name. ! 92: */ ! 93: firstdom = NULL; ! 94: for(tsp=sp; tsp; tsp=tsp->next) { ! 95: gooddom = 0; ! 96: dom = in = NULL; ! 97: for(tp=tsp->this; tp; tp=tp->next) ! 98: if(tp->type && strcmp(tp->type, "in")==0) ! 99: in = tp->value; ! 100: else if(tp->type && strcmp(tp->type, "dom")==0){ ! 101: dom = tp->value; ! 102: if(firstdom==NULL) { ! 103: firstdom = dom; ! 104: gooddom = 1; ! 105: } else { ! 106: if(strcmp(firstdom, dom)==0) ! 107: gooddom = 1; ! 108: } ! 109: } ! 110: if(in){ ! 111: if(!gooddom && dom) ! 112: continue; ! 113: tries++; ! 114: fd = dialip(in, lport, fport, fields, n, ip, ! 115: service); ! 116: if(fd>=0){ ! 117: freeQset(sp); ! 118: return(fd); ! 119: } ! 120: } ! 121: } ! 122: ! 123: /* none worked */ ! 124: freeQset(sp); ! 125: if(tries) ! 126: return ABORT(errno, errstr, NULLINFO); ! 127: else ! 128: return ABORT(ENOENT, "unassigned destination", NULLINFO); ! 129: } ! 130: ! 131: /* ! 132: * order tuples relative to a domain address ! 133: */ ! 134: int ! 135: matchval(np, dp) ! 136: char *np; ! 137: char *dp; ! 138: { ! 139: char *cnp, *cdp; ! 140: int rv = 0; ! 141: ! 142: cnp = np+strlen(np); ! 143: cdp = dp+strlen(dp); ! 144: do { ! 145: while(--cdp>dp) ! 146: if(*cdp=='.') ! 147: break; ! 148: while(--cnp>np) ! 149: if(*cnp=='.') ! 150: break; ! 151: if(strcmp(cdp, cnp)!=0) ! 152: break; ! 153: rv++; ! 154: } while(cdp>dp); ! 155: return rv; ! 156: } ! 157: ! 158: dialalarm() ! 159: { ! 160: } ! 161: ! 162: /* ! 163: * dial one ip address ! 164: * ! 165: * Use a port < 1024 if: ! 166: * a) the caller is root ! 167: * b) we are calling the connection server ! 168: * c) the caller requests us to perform bsd authentication for him ! 169: */ ! 170: dialip(number, lport, fport, fields, n, ip, service) ! 171: char *number; ! 172: int lport, fport; ! 173: char *fields[]; ! 174: int n; ! 175: ipcinfo *ip; ! 176: char *service; ! 177: { ! 178: struct tcpuser tu; ! 179: in_addr faddr; ! 180: int fd; ! 181: int (*oldsig)(); ! 182: int ba; ! 183: ! 184: logevent("trying: %s\n", number); ! 185: faddr = in_aton(number); ! 186: if(faddr==INADDR_ANY) ! 187: return ABORT(ENOENT, "unassigned destination", NULLINFO); ! 188: ba = bsdauth(fields, n); ! 189: ! 190: /* get a channel for the connection */ ! 191: fd = tcp_sock(); ! 192: if (fd < 0) ! 193: return ABORT(EBUSY, "out of output channels", NULLINFO); ! 194: ! 195: /* ! 196: * connect to the remote connection server if there is not a well known ! 197: * port for this service. ! 198: */ ! 199: if(fport<=0){ ! 200: tu.laddr = INADDR_ANY; ! 201: tu.lport = 0; ! 202: tu.faddr = faddr; ! 203: tu.fport = CSPORT; ! 204: tcpoptions(&tu, fields, n, ba, ip); ! 205: errstr = "destination not answering"; ! 206: ! 207: /* ! 208: * give connection servers 5 seconds to answer (if it can) ! 209: */ ! 210: oldsig = signal(SIGALRM, dialalarm); ! 211: alarm(5); ! 212: if (tcp_connect(fd, &tu)>=0) { ! 213: alarm(0); ! 214: signal(SIGALRM, oldsig); ! 215: ! 216: /* ! 217: * send the request ! 218: */ ! 219: ip->name = service; ! 220: if (_info_write(fd, ip)==0) ! 221: if (_reply_read(fd)==0 && errno==0) { ! 222: condition(fd, fields, n, ip->user); ! 223: filloutnames(&tu, ip, CALLOUT); ! 224: return fd; ! 225: } ! 226: } ! 227: alarm(0); ! 228: signal(SIGALRM, oldsig); ! 229: close(fd); ! 230: return -1; ! 231: } else { ! 232: ! 233: /* ! 234: * connect to the well known port ! 235: */ ! 236: fd = tcp_sock(); ! 237: if (fd < 0) ! 238: return ABORT(EBUSY, "out of output channels", NULLINFO); ! 239: tu.laddr = INADDR_ANY; ! 240: tu.lport = lport; ! 241: tu.faddr = faddr; ! 242: tu.fport = fport; ! 243: tcpoptions(&tu, fields, n, ba, ip); ! 244: if (tu.fport<=0) { ! 245: close(fd); ! 246: return ABORT(ENOENT, "unknown service", NULLINFO); ! 247: } ! 248: ! 249: /* ! 250: * give other system 15 seconds to answer (if it can) ! 251: */ ! 252: oldsig = signal(SIGALRM, dialalarm); ! 253: alarm(15); ! 254: if (tcp_connect(fd, &tu)<0) { ! 255: alarm(0); ! 256: signal(SIGALRM, oldsig); ! 257: close(fd); ! 258: return -1; ! 259: } ! 260: alarm(0); ! 261: signal(SIGALRM, oldsig); ! 262: condition(fd, fields, n, ip->user); ! 263: filloutnames(&tu, ip, CALLOUT); ! 264: return fd; ! 265: } ! 266: } ! 267: ! 268: /* return true if bsd authentication is requested */ ! 269: bsdauth(fields, n) ! 270: char *fields[]; ! 271: int n; ! 272: { ! 273: int i; ! 274: ! 275: for (i=0; i<n && fields[i]; i++) ! 276: if (strcmp(fields[i], "bsdauth")==0) ! 277: return 1; ! 278: return 0; ! 279: } ! 280: ! 281: /* create options */ ! 282: tcpoptions(tp, fields, n, bsdauth, ip) ! 283: struct tcpuser *tp; ! 284: char *fields[]; ! 285: ipcinfo *ip; ! 286: { ! 287: int i; ! 288: ! 289: if(bsdauth) ! 290: tp->param = SO_TRUSTED; ! 291: else ! 292: tp->param = ip->uid==0 ? SO_TRUSTED : 0; ! 293: ! 294: for (i=0; i<n && fields[i]; i++) { ! 295: if (strcmp(fields[i], "keepalive")==0) ! 296: tp->param |= SO_KEEPALIVE; ! 297: } ! 298: } ! 299: ! 300: /* condition the connection as requested */ ! 301: condition(fd, fields, n, user) ! 302: int fd; ! 303: char *fields[]; ! 304: char *user; ! 305: { ! 306: int i; ! 307: int dohup=0; ! 308: int dobsd=0; ! 309: int domesg=0; ! 310: ! 311: for (i=0; i<n && fields[i]; i++) { ! 312: if (strcmp(fields[i], "hup")==0) ! 313: dohup = 1; ! 314: if (strcmp(fields[i], "delim")==0) ! 315: domesg = 1; ! 316: if (strcmp(fields[i], "bsdauth")==0){ ! 317: dobsd = 1; ! 318: } ! 319: } ! 320: if (dobsd){ ! 321: if(!user) ! 322: user = "_unknown_"; ! 323: write(fd, "", 1); ! 324: write(fd, user, strlen(user)+1); ! 325: write(fd, user, strlen(user)+1); ! 326: } ! 327: if (dohup){ ! 328: ioctl(fd, TCPIOHUP, 0); ! 329: } ! 330: if (domesg){ ! 331: ioctl(fd, FIOPUSHLD, &rmesg_ld); ! 332: } ! 333: } ! 334: ! 335: /* get the local name out of the connection info */ ! 336: filloutnames(tp, ip, type) ! 337: struct tcpuser *tp; ! 338: ipcinfo *ip; ! 339: { ! 340: static stretch newipcname; ! 341: static stretch fmachine; ! 342: static stretch lmachine; ! 343: static stretch fportname; ! 344: static stretch lportname; ! 345: char *fields[16]; ! 346: ! 347: _strcat(&lmachine, in_ntoa(tp->laddr), (char *)0, (char *)0); ! 348: _strcat(&lportname, "xxxxxxxxxx", (char *)0, (char *)0); ! 349: switch (type) { ! 350: case CALLINCS: ! 351: /* ! 352: * a call from the network via connection server ! 353: */ ! 354: sprintf(lportname.ptr, "tcp.%d", tp->lport); ! 355: _strcat(&fmachine, in_host(tp->faddr), (char *)0, (char *)0); ! 356: ip->myname = lmachine.ptr; ! 357: ip->machine = fmachine.ptr; ! 358: break; ! 359: case CALLIN: ! 360: /* ! 361: * a call from the network ! 362: */ ! 363: sprintf(lportname.ptr, "tcp.%d", tp->lport); ! 364: _strcat(&fmachine, in_host(tp->faddr), (char *)0, (char *)0); ! 365: ip->myname = lmachine.ptr; ! 366: ip->machine = fmachine.ptr; ! 367: break; ! 368: case CALLOUT: ! 369: /* ! 370: * a call to the network ! 371: */ ! 372: sprintf(lportname.ptr, "%d", tp->lport); ! 373: _strcat(&fmachine, in_ntoa(tp->faddr), (char *)0, (char *)0); ! 374: _strcat(&fportname, "xxxxxxxxxx", (char *)0, (char *)0); ! 375: sprintf(fportname.ptr, "%d", tp->fport); ! 376: ip->myname = fmachine.ptr; ! 377: ip->name = fportname.ptr; ! 378: ip->machine = lmachine.ptr; ! 379: break; ! 380: case ANNOUNCE: ! 381: /* ! 382: * an announcement ! 383: */ ! 384: sprintf(lportname.ptr, "%d", tp->lport); ! 385: ip->myname = lmachine.ptr; ! 386: ip->name = lportname.ptr; ! 387: ip->machine = lmachine.ptr; ! 388: break; ! 389: } ! 390: _strcat(&newipcname, lmachine.ptr, "!", lportname.ptr); ! 391: ipcname = newipcname.ptr; ! 392: } ! 393: ! 394: /* break up parameter list */ ! 395: breakparams(ip, fields, n) ! 396: ipcinfo *ip; ! 397: char *fields[]; ! 398: int n; ! 399: { ! 400: static stretch param; ! 401: ! 402: if (*ip->param){ ! 403: _strcat(¶m, ip->param, (char *)0, (char *)0); ! 404: setfields(" \t"); ! 405: n = getmfields(param.ptr, fields, n); ! 406: } else ! 407: n = 0; ! 408: ! 409: return n; ! 410: } ! 411: ! 412: /* announce onto the internet */ ! 413: int ! 414: net_announce(ip) ! 415: ipcinfo *ip; ! 416: { ! 417: int fd, n; ! 418: struct tcpuser tu; ! 419: static stretch dest; ! 420: char *fields[4]; ! 421: in_addr myaddr; ! 422: int port; ! 423: ! 424: /* ! 425: * break the address into host and service ! 426: */ ! 427: _strcat(&dest, ip->name, (char *)0, (char *)0); ! 428: setfields("!"); ! 429: n = getmfields(dest.ptr, fields, 4); ! 430: switch(n){ ! 431: case 0: ! 432: /* accept all calls not specificly asked for */ ! 433: fields[0] = ""; ! 434: fields[1] = ""; ! 435: break; ! 436: case 1: ! 437: /* accept specified address */ ! 438: fields[1] = ""; ! 439: break; ! 440: case 2: ! 441: break; ! 442: default: ! 443: return ABORT(ENOENT, "illegal address", NULLINFO); ! 444: } ! 445: ! 446: /* ! 447: * no address means listen for calls to any address ! 448: */ ! 449: if (*fields[0]) { ! 450: myaddr = in_address(fields[0]); ! 451: if(myaddr==0) ! 452: return ABORT(ENOENT, "illegal address", NULLINFO); ! 453: } else ! 454: myaddr = INADDR_ANY; ! 455: ! 456: /* ! 457: * no port means listen for calls to any port. port '*' means ! 458: * pick me a port to listen on (returned in ipcname) ! 459: */ ! 460: if (*fields[1]){ ! 461: if (strcmp(fields[1], "*")==0) ! 462: port = 0; ! 463: else { ! 464: port = atoi(fields[1]); ! 465: if(port<1024 && ip->uid!=0) ! 466: return ABORT(ENOENT, "illegal port", NULLINFO); ! 467: } ! 468: } else ! 469: port = TCPPORT_ANY; ! 470: ! 471: /* perform the announcement */ ! 472: fd = tcp_sock(); ! 473: if (fd < 0) ! 474: return ABORT(EBUSY, "no more output channels", NULLINFO); ! 475: tu.lport = port; ! 476: tu.laddr = myaddr; ! 477: tu.fport = 0; ! 478: tu.faddr = 0; ! 479: tu.param = ip->uid==0 ? SO_TRUSTED : 0; ! 480: if (tcp_listen(fd, &tu)<0) { ! 481: close(fd); ! 482: return ABORT(EEXIST, "server already exists", NULLINFO); ! 483: } ! 484: filloutnames(&tu, ip, ANNOUNCE); ! 485: return fd; ! 486: } ! 487: ! 488: /* listen for a call in */ ! 489: ipcinfo * ! 490: net_listen(fd) ! 491: int fd; ! 492: { ! 493: static ipcinfo info; ! 494: static char myname[PATHLEN]; ! 495: static char name[PATHLEN]; ! 496: static char machine[PATHLEN]; ! 497: struct tcpuser tu; ! 498: char param[128]; ! 499: char *fields[16]; ! 500: int n; ! 501: extern char *tcptofs(); ! 502: ! 503: info.flags = 0; ! 504: for(;;) { ! 505: tu.param = 0; ! 506: if ((fd = tcp_accept(fd, &tu))<0) { ! 507: logevent("listen: tcp_accept failed-- errno %d\n", errno); ! 508: return NULL; ! 509: } ! 510: if (tu.lport == CSPORT) { ! 511: if (tu.fport > 1023) ! 512: info.uid = info.gid = -1; ! 513: else ! 514: info.uid = info.gid = 0; ! 515: info.user = "_unknown_"; ! 516: if (_info_read(fd, &info)<0) { ! 517: logevent("listen: info_read failed -- errno %d\n", errno); ! 518: close(fd); ! 519: return (ipcinfo *)NULL; ! 520: } ! 521: info.flags |= IPC_HANDOFF; ! 522: ! 523: /* break parameters */ ! 524: n = breakparams(&info, fields, 16); ! 525: condition(fd, fields, n, (char *)0); ! 526: filloutnames(&tu, &info, CALLINCS); ! 527: } else { ! 528: info.user = tu.fport>=1024 ? "_unknown_" : "root"; ! 529: info.param = ""; ! 530: strcpy(name, tcptofs(tu.lport)); ! 531: info.name = name; ! 532: filloutnames(&tu, &info, CALLIN); ! 533: } ! 534: info.flags |= IPC_OPEN; ! 535: info.rfd = fd; ! 536: info.cfd = -1; ! 537: return &info; ! 538: } ! 539: } ! 540: ! 541: /* accept a call */ ! 542: void ! 543: net_accept(ip) ! 544: ipcinfo *ip; ! 545: { ! 546: USE(ip); ! 547: } ! 548: ! 549: /* reject a call - null if a non-cs call */ ! 550: void ! 551: net_reject(ip, no, str) ! 552: ipcinfo *ip; ! 553: int no; ! 554: char *str; ! 555: { ! 556: if (ip->flags&IPC_HANDOFF && ip->rfd>=0) ! 557: _reply_write(ip->rfd, no, str); ! 558: if (ip->rfd>=0) { ! 559: close(ip->rfd); ! 560: ip->rfd = -1; ! 561: } ! 562: } ! 563: ! 564: int ! 565: net_redial(ip) ! 566: ipcinfo *ip; ! 567: { ! 568: return -1; ! 569: } ! 570:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.