AmendHub

Download

jcs

/

wallops

/

tcp.c

 

(View History)

jcs   *: Large reorganization in preparation for multiple chat windows Latest amendment: 42 on 2022-12-11

1 #include <stdio.h>
2 #include <string.h>
3 #include "tcp.h"
4
5 #define RCV_BUFFER_SIZE 1024
6 #define TCP_BUFFER_SIZE 8192
7 #define OPEN_TIMEOUT 60
8
9 short gIPPDriverRefNum;
10
11 pascal void StrToAddrMarkDone(struct hostInfo *hi, char *data);
12
13 unsigned long resolved_ip;
14
15 OSErr
16 _TCPInit(void)
17 {
18 ParamBlockRec pb;
19 OSErr osErr;
20
21 memset(&pb, 0, sizeof(pb));
22
23 gIPPDriverRefNum = -1;
24
25 pb.ioParam.ioCompletion = 0;
26 pb.ioParam.ioNamePtr = "\p.IPP";
27 pb.ioParam.ioPermssn = fsCurPerm;
28
29 osErr = PBOpen(&pb, false);
30 if (noErr == osErr)
31 gIPPDriverRefNum = pb.ioParam.ioRefNum;
32
33 return osErr;
34 }
35
36 OSErr
37 _TCPGetOurIP(ip_addr *ip, long *netMask)
38 {
39 OSErr osErr;
40 GetAddrParamBlock pb;
41
42 memset(&pb, 0, sizeof(pb));
43
44 pb.csCode = ipctlGetAddr;
45 pb.ioCRefNum = gIPPDriverRefNum;
46 pb.ioResult = 1;
47
48 osErr = PBControl((ParmBlkPtr)&pb, true);
49 while (pb.ioResult > 0)
50 ;
51
52 if (pb.ioResult != noErr)
53 return pb.ioResult;
54
55 if (ip != NULL)
56 *ip = pb.ourAddress;
57 if (netMask != NULL)
58 *netMask = pb.ourNetMask;
59
60 return osErr;
61 }
62
63 OSErr
64 _TCPCreate(TCPiopb *pb, StreamPtr *stream, Ptr rcvBufPtr, long rcvBufLen,
65 TCPNotifyProc aNotifyProc, Ptr userDataPtr,
66 TCPIOCompletionProc ioCompletion, Boolean async)
67 {
68 OSErr osErr;
69
70 memset(pb, 0, sizeof(*pb));
71
72 pb->csCode = TCPCreate;
73 pb->ioCompletion = ioCompletion;
74 pb->ioCRefNum = gIPPDriverRefNum;
75 pb->ioResult = 1;
76
77 pb->csParam.create.rcvBuff = rcvBufPtr;
78 pb->csParam.create.rcvBuffLen = rcvBufLen;
79 pb->csParam.create.notifyProc = aNotifyProc;
80 pb->csParam.create.userDataPtr = userDataPtr;
81
82 osErr = PBControl((ParmBlkPtr)pb, async);
83 if (!async && (noErr == osErr)) {
84 *stream = pb->tcpStream;
85 }
86
87 return osErr;
88 }
89
90 /* listen for an incoming connection */
91 OSErr
92 _TCPPassiveOpen(TCPiopb *pb, StreamPtr stream, ip_addr *remoteIP,
93 tcp_port *remotePort, ip_addr *localIP, tcp_port *localPort,
94 Ptr userData, TCPIOCompletionProc ioCompletion, Boolean async)
95 {
96 OSErr osErr;
97 short index;
98
99 memset(pb, 0, sizeof(*pb));
100
101 pb->csCode = TCPPassiveOpen;
102 pb->ioCompletion = ioCompletion;
103 pb->ioCRefNum = gIPPDriverRefNum;
104 pb->tcpStream = stream;
105 pb->ioResult = 1;
106
107 pb->csParam.open.ulpTimeoutAction = 1; /* abort half-open connection */
108 pb->csParam.open.ulpTimeoutValue = 5; /* after 5 seconds */
109 pb->csParam.open.validityFlags = 0xC0;
110 pb->csParam.open.commandTimeoutValue = 0;
111 pb->csParam.open.remoteHost = 0;
112 pb->csParam.open.remotePort = 0;
113 pb->csParam.open.localHost = 0;
114 pb->csParam.open.localPort = *localPort;
115 pb->csParam.open.tosFlags = 0;
116 pb->csParam.open.precedence = 0;
117 pb->csParam.open.dontFrag = 0;
118 pb->csParam.open.timeToLive = 0;
119 pb->csParam.open.security = 0;
120 pb->csParam.open.optionCnt = 0;
121 for (index = 0; index < sizeof(pb->csParam.open.options); ++index)
122 pb->csParam.open.options[index] = 0;
123 pb->csParam.open.userDataPtr = userData;
124
125 osErr = PBControl((ParmBlkPtr) pb, async);
126 if (!async && (osErr == noErr)) {
127 if (remoteIP)
128 *remoteIP = pb->csParam.open.remoteHost;
129 if (remotePort)
130 *remotePort = pb->csParam.open.remotePort;
131 if (localIP)
132 *localIP = pb->csParam.open.localHost;
133 *localPort = pb->csParam.open.localPort;
134 }
135
136 return osErr;
137 }
138
139 /* make an outgoing connection */
140 OSErr
141 _TCPActiveOpen(TCPiopb *pb, StreamPtr stream, ip_addr remoteIP,
142 tcp_port remotePort, ip_addr *localIP, tcp_port *localPort,
143 Ptr userData, TCPIOCompletionProc ioCompletion, Boolean async)
144 {
145 OSErr osErr;
146 short index;
147
148 memset(pb, 0, sizeof(*pb));
149
150 pb->csCode = TCPActiveOpen;
151 pb->ioCompletion = ioCompletion;
152 pb->ioCRefNum = gIPPDriverRefNum;
153 pb->tcpStream = stream;
154 pb->ioResult = 1;
155
156 pb->csParam.open.ulpTimeoutValue = 30;
157 pb->csParam.open.ulpTimeoutAction = 1;
158 pb->csParam.open.validityFlags = 0xC0;
159 #if 0
160 /* not available with this csCode */
161 pb->csParam.open.commandTimeoutValue = 30;
162 #endif
163 pb->csParam.open.remoteHost = remoteIP;
164 pb->csParam.open.remotePort = remotePort;
165 pb->csParam.open.localHost = 0;
166 pb->csParam.open.localPort = *localPort;
167 pb->csParam.open.tosFlags = 0;
168 pb->csParam.open.precedence = 0;
169 pb->csParam.open.dontFrag = 0;
170 pb->csParam.open.timeToLive = 0;
171 pb->csParam.open.security = 0;
172 pb->csParam.open.optionCnt = 0;
173 for (index = 0; index < sizeof(pb->csParam.open.options); ++index)
174 pb->csParam.open.options[index] = 0;
175 pb->csParam.open.userDataPtr = userData;
176
177 osErr = PBControl((ParmBlkPtr) pb, async);
178 if (!async && (noErr == osErr)) {
179 *localIP = pb->csParam.open.localHost;
180 *localPort = pb->csParam.open.localPort;
181 }
182
183 return osErr;
184 }
185
186 OSErr
187 _TCPSend(TCPiopb *pb, StreamPtr stream, wdsEntry *wdsPtr, Ptr userData,
188 TCPIOCompletionProc ioCompletion, Boolean async)
189 {
190 memset(pb, 0, sizeof(*pb));
191
192 pb->csCode = TCPSend;
193 pb->ioCompletion = ioCompletion;
194 pb->ioCRefNum = gIPPDriverRefNum;
195 pb->tcpStream = stream;
196 pb->ioResult = 1;
197
198 pb->csParam.send.ulpTimeoutValue = 30;
199 pb->csParam.send.ulpTimeoutAction = 1;
200 pb->csParam.send.validityFlags = 0xC0;
201 pb->csParam.send.pushFlag = 1; /* XXX */
202 pb->csParam.send.urgentFlag = 0;
203 pb->csParam.send.wdsPtr = (Ptr)wdsPtr;
204 pb->csParam.send.sendFree = 0;
205 pb->csParam.send.sendLength = 0;
206 pb->csParam.send.userDataPtr = userData;
207
208 return PBControl((ParmBlkPtr)pb, async);
209 }
210
211 OSErr
212 _TCPNoCopyRcv(TCPiopb *pb, StreamPtr stream, Ptr rdsPtr,
213 unsigned short rdsLength, Ptr userData, TCPIOCompletionProc ioCompletion,
214 Boolean async)
215 {
216 OSErr osErr;
217
218 memset(pb, 0, sizeof(*pb));
219
220 pb->csCode = TCPNoCopyRcv;
221 pb->ioCompletion = ioCompletion;
222 pb->ioCRefNum = gIPPDriverRefNum;
223 pb->tcpStream = stream;
224 pb->ioResult = 1;
225
226 pb->csParam.receive.commandTimeoutValue = 30;
227 pb->csParam.receive.urgentFlag = 0;
228 pb->csParam.receive.markFlag = 0;
229 pb->csParam.receive.rdsPtr = rdsPtr;
230 pb->csParam.receive.rdsLength = rdsLength;
231 pb->csParam.receive.userDataPtr = userData;
232
233 return PBControl((ParmBlkPtr)pb, async);
234 }
235
236 OSErr
237 _TCPRcv(TCPiopb *pb, StreamPtr stream, Ptr rcvBufPtr,
238 unsigned short *rcvBufLen, Ptr userData, TCPIOCompletionProc ioCompletion,
239 Boolean async)
240 {
241 OSErr osErr;
242
243 memset(pb, 0, sizeof(*pb));
244
245 pb->csCode = TCPRcv;
246 pb->ioCompletion = ioCompletion;
247 pb->ioCRefNum = gIPPDriverRefNum;
248 pb->tcpStream = stream;
249 pb->ioResult = 1;
250
251 pb->csParam.receive.commandTimeoutValue = 30;
252 pb->csParam.receive.urgentFlag = 0;
253 pb->csParam.receive.markFlag = 0;
254 pb->csParam.receive.rcvBuff = rcvBufPtr;
255 pb->csParam.receive.rcvBuffLen = *rcvBufLen;
256 pb->csParam.receive.userDataPtr = userData;
257
258 osErr = PBControl((ParmBlkPtr)pb, async);
259 if (!async)
260 *rcvBufLen = pb->csParam.receive.rcvBuffLen;
261
262 return osErr;
263 }
264
265 OSErr
266 _TCPBfrReturn(TCPiopb *pb, StreamPtr stream, Ptr rdsPtr, Ptr userData,
267 TCPIOCompletionProc ioCompletion, Boolean async)
268 {
269 memset(pb, 0, sizeof(*pb));
270
271 pb->csCode = TCPRcvBfrReturn;
272 pb->ioCompletion = ioCompletion;
273 pb->ioCRefNum = gIPPDriverRefNum;
274 pb->tcpStream = stream;
275 pb->ioResult = 1;
276
277 pb->csParam.receive.rdsPtr = rdsPtr;
278 pb->csParam.receive.userDataPtr = userData;
279
280 return PBControl((ParmBlkPtr)pb, async);
281 }
282
283 OSErr
284 _TCPClose(TCPiopb *pb, StreamPtr stream, Ptr userData,
285 TCPIOCompletionProc ioCompletion, Boolean async)
286 {
287 memset(pb, 0, sizeof(*pb));
288
289 pb->csCode = TCPClose;
290 pb->ioCompletion = ioCompletion;
291 pb->ioCRefNum = gIPPDriverRefNum;
292 pb->tcpStream = stream;
293 pb->ioResult = 1;
294
295 pb->csParam.close.ulpTimeoutValue = 30;
296 pb->csParam.close.ulpTimeoutAction = 1;
297 pb->csParam.close.validityFlags = 0xC0;
298 pb->csParam.close.userDataPtr = userData;
299
300 return PBControl((ParmBlkPtr)pb, async);
301 }
302
303 OSErr
304 _TCPAbort(TCPiopb *pb, StreamPtr stream, Ptr userData,
305 TCPIOCompletionProc ioCompletion, Boolean async)
306 {
307 memset(pb, 0, sizeof(*pb));
308
309 pb->csCode = TCPAbort;
310 pb->ioCompletion = ioCompletion;
311 pb->ioCRefNum = gIPPDriverRefNum;
312 pb->tcpStream = stream;
313 pb->ioResult = 1;
314
315 pb->csParam.abort.userDataPtr = userData;
316
317 return PBControl((ParmBlkPtr)pb, async);
318 }
319
320 OSErr
321 _TCPStatus(TCPiopb *pb, StreamPtr stream, struct TCPStatusPB *status,
322 Ptr userData, TCPIOCompletionProc ioCompletion, Boolean async)
323 {
324 OSErr osErr;
325
326 memset(pb, 0, sizeof(*pb));
327
328 pb->csCode = TCPStatus;
329 pb->ioCompletion = ioCompletion;
330 pb->ioCRefNum = gIPPDriverRefNum;
331 pb->tcpStream = stream;
332 pb->csParam.status.userDataPtr = userData;
333 pb->ioResult = 1;
334
335 osErr = PBControl((ParmBlkPtr)pb, async);
336 if (!async && (noErr == osErr)) {
337 *status = pb->csParam.status;
338 }
339
340 return osErr;
341 }
342
343 OSErr
344 _TCPRelease(TCPiopb *pb, StreamPtr stream, Ptr userData,
345 TCPIOCompletionProc ioCompletion, Boolean async)
346 {
347 OSErr osErr;
348
349 memset(pb, 0, sizeof(*pb));
350
351 pb->csCode = TCPRelease;
352 pb->ioCompletion = ioCompletion;
353 pb->ioCRefNum = gIPPDriverRefNum;
354 pb->tcpStream = stream;
355 pb->ioResult = 1;
356
357 pb->csParam.status.userDataPtr = userData;
358
359 osErr = PBControl((ParmBlkPtr)pb, async);
360
361 return osErr;
362 }
363
364 OSErr
365 _UDPMaxMTUSize(UDPiopb *pb, short *mtu)
366 {
367 OSErr osErr;
368
369 memset(pb, 0, sizeof(*pb));
370
371 pb->csCode = UDPMaxMTUSize;
372 pb->ioCRefNum = gIPPDriverRefNum;
373 pb->ioResult = 1;
374
375 pb->csParam.mtu.remoteHost = (ip_addr)0;
376
377 osErr = PBControl((ParmBlkPtr)pb, false);
378
379 if (osErr == noErr)
380 *mtu = pb->csParam.mtu.mtuSize;
381
382 return osErr;
383 }
384
385 /* convenience functions */
386
387 static pascal void
388 StrToAddrMarkDone(struct hostInfo *hi, char *data)
389 {
390 volatile int *done = (int *)data;
391 *done = 1;
392 }
393
394 OSErr
395 TCPResolveName(char *name, unsigned long *ipAddress)
396 {
397 OSErr osErr;
398 struct hostInfo aHostInfo;
399 volatile int done = 0;
400
401 osErr = OpenResolver(nil);
402 if (osErr)
403 return osErr;
404
405 osErr = StrToAddr(name, &aHostInfo, (ResultProcPtr)StrToAddrMarkDone,
406 (char *)&done);
407
408 if (osErr == cacheFault) {
409 /* StrToAddrMarkDone will set done when DNS resolution finishes */
410 while (!done)
411 ;
412 }
413
414 if ((aHostInfo.rtnCode == noErr) || (aHostInfo.rtnCode == cacheFault)) {
415 /* use the first IP address for this host */
416 *ipAddress = aHostInfo.addr[0];
417 osErr = noErr;
418 } else
419 osErr = aHostInfo.rtnCode;
420
421 CloseResolver();
422 return osErr;
423 }
424
425 long
426 ip2long(char *ip)
427 {
428 long address = 0;
429 int dotcount = 0, i;
430 unsigned int b = 0;
431
432 for (i = 0; ip[i] != 0; i++) {
433 if (ip[i] == '.') {
434 if (++dotcount > 3)
435 return (0);
436 address <<= 8;
437 address |= b;
438 b = 0;
439 } else if (ip[i] >= '0' && ip[i] <= '9') {
440 b *= 10;
441 b += (ip[i] - '0');
442 if (b > 255)
443 return (0);
444 } else
445 return (0);
446 }
447
448 if (dotcount != 3)
449 return (0);
450 address <<= 8;
451 address |= b;
452 return address;
453 }
454
455 void
456 long2ip(unsigned long num, char *ip)
457 {
458 unsigned char *tmp = (unsigned char *)&num;
459 (void)sprintf(ip, (const char *)"%d.%d.%d.%d", tmp[0], tmp[1], tmp[2], tmp[3]);
460 }
461
462 #define SOCKS_VERSION_SOCKS5 0x5
463 #define SOCKS_METHOD_AUTH_NONE 0x0
464 #define SOCKS_REQUEST_CONNECT 0x1
465 #define SOCKS_REQUEST_ATYP_DOMAINNAME 0x3
466 #define SOCKS_REPLY_SUCCESS 0x0
467
468 OSErr
469 SOCKS5TCPActiveOpen(TCPiopb *pb, StreamPtr stream, ip_addr socks_ip,
470 tcp_port socks_port, char *remote_host, tcp_port remote_port,
471 ip_addr *local_ip, tcp_port *local_port, Ptr user_data,
472 TCPIOCompletionProc io_completion, Boolean async)
473 {
474 OSErr err;
475 TCPStatusPB status_pb;
476 wdsEntry wds[2];
477 char data[255] = { 0 };
478 unsigned short len, remote_host_len;
479
480 remote_host_len = strlen(remote_host);
481 if (remote_host_len + 7 > sizeof(data))
482 return -1;
483
484 err = _TCPActiveOpen(pb, stream, socks_ip, socks_port, local_ip,
485 local_port, user_data, io_completion, async);
486 if (err != noErr)
487 return err;
488
489 data[0] = SOCKS_VERSION_SOCKS5;
490 data[1] = 1; /* nmethods */
491 data[2] = SOCKS_METHOD_AUTH_NONE;
492
493 memset(&wds, 0, sizeof(wds));
494 wds[0].ptr = (Ptr)&data;
495 wds[0].length = 3;
496
497 err = _TCPSend(pb, stream, wds, nil, nil, false);
498 if (err)
499 goto fail;
500
501 for (;;) {
502 err = _TCPStatus(pb, stream, &status_pb, nil, nil, false);
503 if (err != noErr)
504 goto fail;
505
506 if (status_pb.amtUnreadData >= 2)
507 break;
508 }
509
510 len = 2;
511 err = _TCPRcv(pb, stream, (Ptr)&data, &len, nil, nil, false);
512 if (err != noErr)
513 goto fail;
514
515 if (data[0] != SOCKS_VERSION_SOCKS5 || data[1] != SOCKS_METHOD_AUTH_NONE)
516 goto fail;
517
518 len = 0;
519 data[len++] = SOCKS_VERSION_SOCKS5;
520 data[len++] = SOCKS_REQUEST_CONNECT;
521 data[len++] = 0; /* reserved */
522 data[len++] = SOCKS_REQUEST_ATYP_DOMAINNAME;
523 data[len++] = remote_host_len;
524 memcpy(data + len, remote_host, remote_host_len);
525 len += remote_host_len;
526 data[len++] = (remote_port >> 8);
527 data[len++] = (remote_port & 0xff);
528
529 memset(&wds, 0, sizeof(wds));
530 wds[0].ptr = (Ptr)&data;
531 wds[0].length = len;
532
533 err = _TCPSend(pb, stream, wds, nil, nil, false);
534 if (err)
535 goto fail;
536
537 for (;;) {
538 err = _TCPStatus(pb, stream, &status_pb, nil, nil, false);
539 if (err != noErr)
540 goto fail;
541
542 if (status_pb.amtUnreadData >= 7)
543 break;
544 }
545
546 len = status_pb.amtUnreadData;
547 if (len > sizeof(data))
548 len = sizeof(data);
549 err = _TCPRcv(pb, stream, (Ptr)&data, &len, nil, nil, false);
550 if (err != noErr)
551 goto fail;
552
553 if (data[0] != SOCKS_VERSION_SOCKS5 || data[1] != SOCKS_REPLY_SUCCESS)
554 goto fail;
555
556 return noErr;
557
558 fail:
559 _TCPClose(pb, stream, nil, nil, false);
560 return err;
561 }