Annotation of researchv10no/ipc/mgrs/tcpmgr/dial.c, revision 1.1.1.1

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(&param, 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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.