|
|
1.1 root 1: #include <sys/types.h>
2: #include <sys/stat.h>
3: #include <sys/filio.h>
4: #include "dk.h"
5: #include <stdio.h>
6: #include <signal.h>
7: #include <errno.h>
8: #include <ipc.h>
9: #include <libc.h>
10: #include "defs.h"
11: #include <dkwindow.h>
12: #include <sys/dkio.h>
13:
14: /* imported */
15: extern int uxp_ld;
16: extern int dkp_ld;
17: extern int errno;
18: extern int unit;
19:
20: enum { dial, announce, redial };
21:
22:
23: static int
24: gettraffic(ip)
25: ipcinfo *ip;
26: {
27: char *dp;
28:
29: /* get type of request and properties */
30: for(dp = ip->param; *dp; dp++) {
31: for(;*dp && *dp==' '; dp++);
32: if (strncmp(dp, "heavy", 5)==0 && (dp[5]=='\0'||dp[5]==' '))
33: return 2;
34: for(;*dp && *dp!=' '; dp++);
35: }
36: return 0;
37: }
38:
39: int
40: net_dial(ip)
41: ipcinfo *ip;
42: {
43: int fd;
44: int ctlfd;
45: int traffic;
46: int chan;
47:
48: traffic = gettraffic(ip);
49: fd = dkchan(&traffic, unit, &chan, &ctlfd);
50: if (fd < 0)
51: return ABORT(EBUSY, "out of output channels", NULLINFO);
52: return dkdial(fd, ctlfd, ip, traffic, chan, dial);
53: }
54:
55: int
56: net_announce(ip)
57: ipcinfo *ip;
58: {
59: int fd;
60: int ctlfd;
61: int traffic;
62: int chan;
63:
64: /*
65: * hack: assertively set unit
66: * when announcing, use traffic type to decide on interface to use.
67: * otherwise, we could announce on the wrong interface.
68: * bug: dkchan tries the other interface, so could still
69: * end up on the wrong one if the right one is full
70: */
71: traffic = gettraffic(ip);
72: if (unit == 'b') {
73: switch(traffic){
74: case 0:
75: unit = '0';
76: break;
77: case 2:
78: unit = '2';
79: break;
80: }
81: }
82: fd = dkchan(&traffic, unit, &chan, &ctlfd);
83: if (fd < 0)
84: return ABORT(EBUSY, "out of output channels", NULLINFO);
85: return dkdial(fd, ctlfd, ip, traffic, chan, announce);
86: }
87:
88: int
89: net_redial(ip)
90: ipcinfo *ip;
91: {
92: int traffic;
93: int chan;
94: int ctlfd;
95:
96: /*
97: * find unit, traffic, and channel
98: */
99: if(dkid(ip->cfd, unit, &traffic, &chan, &ctlfd)<0)
100: return -1;
101: return dkdial(ip->cfd, ctlfd, ip, traffic, chan, redial);
102: }
103:
104: int
105: dkdial(fd, listener, ip, traffic, chan, operation)
106: ipcinfo *ip;
107: {
108: int i;
109: struct dialout d;
110: char dialstr[128];
111: char dialtone[2];
112: register char *dp, *cp;
113: struct dialout reply;
114: int al_catch();
115: long window;
116: char ws[8];
117:
118: /*
119: * restart URP on the channel
120: */
121: signal(SIGALRM, al_catch);
122: dkproto(fd, dkp_ld);
123: ioctl(fd, FIOPUSHLD, &uxp_ld);
124:
125: /* set up the parameter block for the initial request */
126: switch(operation){
127: case dial:
128: d.type = T_SRV;
129: d.srv = D_DIAL;
130: break;
131: case announce:
132: d.type = T_SRV;
133: d.srv = D_SERV;
134: break;
135: case redial:
136: d.type = T_CHG;
137: d.srv = D_REDIAL;
138: break;
139: }
140: d.param0l = chan;
141: d.param0h = chan>>8;
142: d.param1l = traffic;
143: d.param1h = traffic>>8;
144: d.param2l = 0;
145: d.param2h = 0;
146: d.param3l = 0;
147: d.param3h = 0;
148: d.param4l = ip->uid;
149: d.param4h = ip->uid>>8;
150:
151: /*
152: * Make dial string.
153: * Convert first two '!'s to '.'s to comply with generic's form
154: * of destination.service[.more-things]. Escape any '.'s in the
155: * service part with '\'s.
156: */
157: for(i=0, cp=ip->name, dp=dialstr; *cp; cp++)
158: if (i<2 && *cp=='!'){
159: *dp++ = '.';
160: i++;
161: } else if (i==1 && *cp=='.') {
162: *dp++ = '\\';
163: *dp++ = '.';
164: } else if (*cp=='\n') {
165: close(fd);
166: return ABORT(EACCES, "illegal dial string", NULLINFO);
167: } else
168: *dp++ = *cp;
169: *dp = '\0';
170: switch(operation){
171: case dial:
172: strcat(dialstr, "\n");
173: strcat(dialstr, ip->user);
174: break;
175: case redial:
176: strcat(dialstr, "\n");
177: strcat(dialstr, ip->user);
178: strcat(dialstr, "\n");
179: strcat(dialstr, ip->machine);
180: break;
181: }
182:
183: /*
184: * send request on common signalling channel
185: */
186: alarm(15);
187: i = write(listener, (char *)&d, sizeof(d));
188: close(listener);
189: if (i != sizeof(d)) {
190: alarm(0);
191: close(fd);
192: ip->cfd = -1;
193: return ABORT(EIO, "can't dial out on dk", NULLINFO);
194: }
195:
196: /*
197: * wait for dial tone (REDIAL only)
198: */
199: if(operation==redial && (read(fd, dialtone, 1)!=1 || *dialtone!='O')) {
200: alarm(0);
201: close(fd);
202: ip->cfd = -1;
203: return ABORT(EIO, "no dialtone on dk", NULLINFO);
204: }
205:
206: /*
207: * dial out
208: */
209: alarm(60);
210: ioctl(fd, DIOCSTOP, 0); /* hold back user data */
211: write(fd, dialstr, strlen(dialstr));
212: if(operation==redial){
213: alarm(0);
214: return fd;
215: }
216:
217: /*
218: * get reply back (REDIAL never gets here)
219: */
220: i = read(fd, (char *)&reply, sizeof reply);
221: alarm(0);
222: if (i <= 0) {
223: close(fd);
224: return ABORT(EIO,"remote system doesn't respond",
225: (ipcinfo *)NULL);
226: }
227:
228: /*
229: * successful reply, analyze it
230: */
231: i = (reply.param1h<<8) | reply.param1l;
232: if (reply.srv!=D_OPEN) {
233: close(fd);
234: dktouerr(i&0x7f);
235: return -1;
236: }
237: if (W_VALID(i)){
238: /*
239: * a 1127 window negotiation
240: */
241: window = W_VALUE(W_DEST(i));
242: } else if(i>2 && i<31){
243: /*
244: * a generic window negotiation
245: */
246: window = 1<<i;
247: } else
248: window = 0;
249: logevent("out window(%d)\n", window);
250: dkproto(fd, dkp_ld);
251: ioctl(fd, FIOPOPLD, 0); /* dump rdk */
252: setwins(fd, window);
253: ip->myname = "";
254: ip->machine = "";
255: return fd;
256: }
257:
258: al_catch()
259: {
260: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.