|
|
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.