AmendHub

Download

jcs

/

wallops

/

tcp.c

 

(View History)

jcs   tcp: Sync with upstream, add atexit destroyer Latest amendment: 51 on 2024-08-30

1 /*
2 * Copyright (c) 2020 joshua stein <jcs@jcs.org>
3 * Copyright (c) 1990-1992 by the University of Illinois Board of Trustees
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include "tcp.h"
22
23 #define RCV_BUFFER_SIZE 1024
24 #define TCP_BUFFER_SIZE 8192
25 #define OPEN_TIMEOUT 60
26
27 short gIPPDriverRefNum;
28
29 static short _TCPAtexitInstalled = 0;
30 static StreamPtr _TCPStreams[10] = { 0 };
31
32 void _TCPAtexit(void);
33
34 OSErr
35 _TCPInit(void)
36 {
37 ParamBlockRec pb;
38 OSErr osErr;
39
40 memset(&pb, 0, sizeof(pb));
41
42 gIPPDriverRefNum = -1;
43
44 pb.ioParam.ioCompletion = 0;
45 pb.ioParam.ioNamePtr = "\p.IPP";
46 pb.ioParam.ioPermssn = fsCurPerm;
47
48 osErr = PBOpen(&pb, false);
49 if (noErr == osErr)
50 gIPPDriverRefNum = pb.ioParam.ioRefNum;
51
52 if (!_TCPAtexitInstalled) {
53 _atexit(_TCPAtexit);
54 _TCPAtexitInstalled = 1;
55 }
56
57 return osErr;
58 }
59
60 void
61 _TCPAtexit(void)
62 {
63 short n;
64 TCPiopb pb = { 0 };
65
66 for (n = 0; n < (sizeof(_TCPStreams) / sizeof(_TCPStreams[0])); n++) {
67 if (_TCPStreams[n] != 0) {
68 _TCPAbort(&pb, _TCPStreams[n], nil, nil, false);
69 _TCPRelease(&pb, _TCPStreams[n], nil, nil, false);
70 _TCPStreams[n] = 0;
71 }
72 }
73 }
74
75 OSErr
76 _TCPGetOurIP(ip_addr *ip, long *netMask)
77 {
78 OSErr osErr;
79 GetAddrParamBlock pb;
80
81 memset(&pb, 0, sizeof(pb));
82
83 pb.csCode = ipctlGetAddr;
84 pb.ioCRefNum = gIPPDriverRefNum;
85 pb.ioResult = 1;
86
87 osErr = PBControl((ParmBlkPtr)&pb, true);
88 while (pb.ioResult > 0)
89 ;
90
91 if (pb.ioResult != noErr)
92 return pb.ioResult;
93
94 if (ip != NULL)
95 *ip = pb.ourAddress;
96 if (netMask != NULL)
97 *netMask = pb.ourNetMask;
98
99 return osErr;
100 }
101
102 OSErr
103 _TCPCreate(TCPiopb *pb, StreamPtr *stream, Ptr rcvBufPtr, long rcvBufLen,
104 TCPNotifyProc aNotifyProc, Ptr userDataPtr,
105 TCPIOCompletionProc ioCompletion, Boolean async)
106 {
107 OSErr osErr;
108 short n;
109
110 memset(pb, 0, sizeof(*pb));
111
112 pb->csCode = TCPCreate;
113 pb->ioCompletion = ioCompletion;
114 pb->ioCRefNum = gIPPDriverRefNum;
115 pb->ioResult = 1;
116
117 pb->csParam.create.rcvBuff = rcvBufPtr;
118 pb->csParam.create.rcvBuffLen = rcvBufLen;
119 pb->csParam.create.notifyProc = aNotifyProc;
120 pb->csParam.create.userDataPtr = userDataPtr;
121
122 osErr = PBControl((ParmBlkPtr)pb, async);
123 if (!async && (noErr == osErr)) {
124 *stream = pb->tcpStream;
125
126 for (n = 0; n < (sizeof(_TCPStreams) / sizeof(_TCPStreams[0])); n++) {
127 if (_TCPStreams[n] == 0) {
128 _TCPStreams[n] = pb->tcpStream;
129 break;
130 }
131 }
132 }
133
134 return osErr;
135 }
136
137 /* listen for an incoming connection */
138 OSErr
139 _TCPPassiveOpen(TCPiopb *pb, StreamPtr stream, ip_addr *remoteIP,
140 tcp_port *remotePort, ip_addr *localIP, tcp_port *localPort,
141 Ptr userData, TCPIOCompletionProc ioCompletion, Boolean async)
142 {
143 OSErr osErr;
144
145 memset(pb, 0, sizeof(*pb));
146
147 pb->csCode = TCPPassiveOpen;
148 pb->ioCompletion = ioCompletion;
149 pb->ioCRefNum = gIPPDriverRefNum;
150 pb->tcpStream = stream;
151 pb->ioResult = 1;
152
153 pb->csParam.open.ulpTimeoutAction = 1; /* abort half-open connection */
154 pb->csParam.open.ulpTimeoutValue = 5; /* after 5 seconds */
155 pb->csParam.open.validityFlags = 0xC0;
156 pb->csParam.open.commandTimeoutValue = 0;
157 pb->csParam.open.remoteHost = 0;
158 pb->csParam.open.remotePort = 0;
159 pb->csParam.open.localHost = 0;
160 pb->csParam.open.localPort = *localPort;
161 pb->csParam.open.tosFlags = 0x1; /* low delay */
162 pb->csParam.open.precedence = 0;
163 pb->csParam.open.dontFrag = 0;
164 pb->csParam.open.timeToLive = 0;
165 pb->csParam.open.security = 0;
166 pb->csParam.open.optionCnt = 0;
167 pb->csParam.open.userDataPtr = userData;
168
169 osErr = PBControl((ParmBlkPtr) pb, async);
170 if (!async && (osErr == noErr)) {
171 if (remoteIP)
172 *remoteIP = pb->csParam.open.remoteHost;
173 if (remotePort)
174 *remotePort = pb->csParam.open.remotePort;
175 if (localIP)
176 *localIP = pb->csParam.open.localHost;
177 *localPort = pb->csParam.open.localPort;
178 }
179
180 return osErr;
181 }
182
183 /* make an outgoing connection */
184 OSErr
185 _TCPActiveOpen(TCPiopb *pb, StreamPtr stream, ip_addr remoteIP,
186 tcp_port remotePort, ip_addr *localIP, tcp_port *localPort,
187 Ptr userData, TCPIOCompletionProc ioCompletion, Boolean async)
188 {
189 OSErr osErr;
190 short index;
191
192 memset(pb, 0, sizeof(*pb));
193
194 pb->csCode = TCPActiveOpen;
195 pb->ioCompletion = ioCompletion;
196 pb->ioCRefNum = gIPPDriverRefNum;
197 pb->tcpStream = stream;
198 pb->ioResult = 1;
199
200 pb->csParam.open.ulpTimeoutValue = 30;
201 pb->csParam.open.ulpTimeoutAction = 1;
202 pb->csParam.open.validityFlags = 0xC0;
203 #if 0
204 /* not available with this csCode */
205 pb->csParam.open.commandTimeoutValue = 30;
206 #endif
207 pb->csParam.open.remoteHost = remoteIP;
208 pb->csParam.open.remotePort = remotePort;
209 pb->csParam.open.localHost = 0;
210 pb->csParam.open.localPort = *localPort;
211 pb->csParam.open.tosFlags = 0;
212 pb->csParam.open.precedence = 0;
213 pb->csParam.open.dontFrag = 0;
214 pb->csParam.open.timeToLive = 0;
215 pb->csParam.open.security = 0;
216 pb->csParam.open.optionCnt = 0;
217 for (index = 0; index < sizeof(pb->csParam.open.options); ++index)
218 pb->csParam.open.options[index] = 0;
219 pb->csParam.open.userDataPtr = userData;
220
221 osErr = PBControl((ParmBlkPtr) pb, async);
222 if (!async && (osErr == noErr)) {
223 *localIP = pb->csParam.open.localHost;
224 *localPort = pb->csParam.open.localPort;
225 }
226
227 return osErr;
228 }
229
230 OSErr
231 _TCPSend(TCPiopb *pb, StreamPtr stream, wdsEntry *wdsPtr, Ptr userData,
232 TCPIOCompletionProc ioCompletion, Boolean async)
233 {
234 memset(pb, 0, sizeof(*pb));
235
236 pb->csCode = TCPSend;
237 pb->ioCompletion = ioCompletion;
238 pb->ioCRefNum = gIPPDriverRefNum;
239 pb->tcpStream = stream;
240 pb->ioResult = 1;
241
242 pb->csParam.send.ulpTimeoutValue = 30;
243 pb->csParam.send.ulpTimeoutAction = 1;
244 pb->csParam.send.validityFlags = 0xC0;
245 pb->csParam.send.pushFlag = 1; /* XXX */
246 pb->csParam.send.urgentFlag = 0;
247 pb->csParam.send.wdsPtr = (Ptr)wdsPtr;
248 pb->csParam.send.sendFree = 0;
249 pb->csParam.send.sendLength = 0;
250 pb->csParam.send.userDataPtr = userData;
251
252 return PBControl((ParmBlkPtr)pb, async);
253 }
254
255 OSErr
256 _TCPNoCopyRcv(TCPiopb *pb, StreamPtr stream, Ptr rdsPtr,
257 unsigned short rdsLength, Ptr userData, TCPIOCompletionProc ioCompletion,
258 Boolean async)
259 {
260 memset(pb, 0, sizeof(*pb));
261
262 pb->csCode = TCPNoCopyRcv;
263 pb->ioCompletion = ioCompletion;
264 pb->ioCRefNum = gIPPDriverRefNum;
265 pb->tcpStream = stream;
266 pb->ioResult = 1;
267
268 pb->csParam.receive.commandTimeoutValue = 30;
269 pb->csParam.receive.urgentFlag = 0;
270 pb->csParam.receive.markFlag = 0;
271 pb->csParam.receive.rdsPtr = rdsPtr;
272 pb->csParam.receive.rdsLength = rdsLength;
273 pb->csParam.receive.userDataPtr = userData;
274
275 return PBControl((ParmBlkPtr)pb, async);
276 }
277
278 OSErr
279 _TCPRcv(TCPiopb *pb, StreamPtr stream, Ptr rcvBufPtr,
280 unsigned short *rcvBufLen, Ptr userData, TCPIOCompletionProc ioCompletion,
281 Boolean async)
282 {
283 OSErr osErr;
284
285 memset(pb, 0, sizeof(*pb));
286
287 pb->csCode = TCPRcv;
288 pb->ioCompletion = ioCompletion;
289 pb->ioCRefNum = gIPPDriverRefNum;
290 pb->tcpStream = stream;
291 pb->ioResult = 1;
292
293 pb->csParam.receive.commandTimeoutValue = 30;
294 pb->csParam.receive.urgentFlag = 0;
295 pb->csParam.receive.markFlag = 0;
296 pb->csParam.receive.rcvBuff = rcvBufPtr;
297 pb->csParam.receive.rcvBuffLen = *rcvBufLen;
298 pb->csParam.receive.userDataPtr = userData;
299
300 osErr = PBControl((ParmBlkPtr)pb, async);
301 if (!async)
302 *rcvBufLen = pb->csParam.receive.rcvBuffLen;
303
304 return osErr;
305 }
306
307 OSErr
308 _TCPBfrReturn(TCPiopb *pb, StreamPtr stream, Ptr rdsPtr, Ptr userData,
309 TCPIOCompletionProc ioCompletion, Boolean async)
310 {
311 memset(pb, 0, sizeof(*pb));
312
313 pb->csCode = TCPRcvBfrReturn;
314 pb->ioCompletion = ioCompletion;
315 pb->ioCRefNum = gIPPDriverRefNum;
316 pb->tcpStream = stream;
317 pb->ioResult = 1;
318
319 pb->csParam.receive.rdsPtr = rdsPtr;
320 pb->csParam.receive.userDataPtr = userData;
321
322 return PBControl((ParmBlkPtr)pb, async);
323 }
324
325 OSErr
326 _TCPClose(TCPiopb *pb, StreamPtr stream, Ptr userData,
327 TCPIOCompletionProc ioCompletion, Boolean async)
328 {
329 memset(pb, 0, sizeof(*pb));
330
331 pb->csCode = TCPClose;
332 pb->ioCompletion = ioCompletion;
333 pb->ioCRefNum = gIPPDriverRefNum;
334 pb->tcpStream = stream;
335 pb->ioResult = 1;
336
337 pb->csParam.close.ulpTimeoutValue = 30;
338 pb->csParam.close.ulpTimeoutAction = 1;
339 pb->csParam.close.validityFlags = 0xC0;
340 pb->csParam.close.userDataPtr = userData;
341
342 return PBControl((ParmBlkPtr)pb, async);
343 }
344
345 OSErr
346 _TCPAbort(TCPiopb *pb, StreamPtr stream, Ptr userData,
347 TCPIOCompletionProc ioCompletion, Boolean async)
348 {
349 memset(pb, 0, sizeof(*pb));
350
351 pb->csCode = TCPAbort;
352 pb->ioCompletion = ioCompletion;
353 pb->ioCRefNum = gIPPDriverRefNum;
354 pb->tcpStream = stream;
355 pb->ioResult = 1;
356
357 pb->csParam.abort.userDataPtr = userData;
358
359 return PBControl((ParmBlkPtr)pb, async);
360 }
361
362 OSErr
363 _TCPStatus(TCPiopb *pb, StreamPtr stream, struct TCPStatusPB *status,
364 Ptr userData, TCPIOCompletionProc ioCompletion, Boolean async)
365 {
366 OSErr osErr;
367
368 pb->ioCompletion = ioCompletion;
369 pb->ioResult = 1;
370 pb->ioNamePtr = 0;
371 pb->ioVRefNum = 0;
372 pb->ioCRefNum = gIPPDriverRefNum;
373 pb->csCode = TCPStatus;
374 pb->tcpStream = stream;
375 pb->csParam.status.userDataPtr = userData;
376
377 osErr = PBControl((ParmBlkPtr)pb, async);
378 if (!async && (noErr == osErr)) {
379 *status = pb->csParam.status;
380 }
381
382 return osErr;
383 }
384
385 OSErr
386 _TCPRelease(TCPiopb *pb, StreamPtr stream, Ptr userData,
387 TCPIOCompletionProc ioCompletion, Boolean async)
388 {
389 OSErr osErr;
390 short n;
391
392 memset(pb, 0, sizeof(*pb));
393
394 pb->csCode = TCPRelease;
395 pb->ioCompletion = ioCompletion;
396 pb->ioCRefNum = gIPPDriverRefNum;
397 pb->tcpStream = stream;
398 pb->ioResult = 1;
399
400 pb->csParam.status.userDataPtr = userData;
401
402 osErr = PBControl((ParmBlkPtr)pb, async);
403
404 for (n = 0; n < (sizeof(_TCPStreams) / sizeof(_TCPStreams[0])); n++) {
405 if (_TCPStreams[n] == stream) {
406 _TCPStreams[n] = 0;
407 break;
408 }
409 }
410
411 return osErr;
412 }
413
414 OSErr
415 _UDPMaxMTUSize(UDPiopb *pb, short *mtu)
416 {
417 OSErr osErr;
418
419 memset(pb, 0, sizeof(*pb));
420
421 pb->csCode = UDPMaxMTUSize;
422 pb->ioCRefNum = gIPPDriverRefNum;
423 pb->ioResult = 1;
424
425 pb->csParam.mtu.remoteHost = (ip_addr)0;
426
427 osErr = PBControl((ParmBlkPtr)pb, false);
428
429 if (osErr == noErr)
430 *mtu = pb->csParam.mtu.mtuSize;
431
432 return osErr;
433 }
434
435 OSErr
436 _UDPCreate(UDPiopb *pb, StreamPtr *stream, Ptr rcvBufPtr, long rcvBufLen,
437 UDPNotifyProc aNotifyProc, Ptr userDataPtr,
438 UDPIOCompletionProc ioCompletion, Boolean async)
439 {
440 OSErr osErr;
441
442 memset(pb, 0, sizeof(*pb));
443
444 pb->csCode = UDPCreate;
445 pb->ioCompletion = ioCompletion;
446 pb->ioCRefNum = gIPPDriverRefNum;
447 pb->ioResult = 1;
448
449 pb->csParam.create.rcvBuff = rcvBufPtr;
450 pb->csParam.create.rcvBuffLen = rcvBufLen;
451 pb->csParam.create.notifyProc = aNotifyProc;
452 pb->csParam.create.userDataPtr = userDataPtr;
453
454 osErr = PBControl((ParmBlkPtr)pb, async);
455 if (!async && (noErr == osErr)) {
456 *stream = pb->udpStream;
457 }
458
459 return osErr;
460 }
461
462 OSErr
463 _UDPSend(UDPiopb *pb, StreamPtr stream, wdsEntry *wdsPtr, ip_addr remoteIP,
464 udp_port remotePort, Ptr userData, UDPIOCompletionProc ioCompletion,
465 Boolean async)
466 {
467 memset(pb, 0, sizeof(*pb));
468
469 pb->csCode = UDPWrite;
470 pb->ioCompletion = ioCompletion;
471 pb->ioCRefNum = gIPPDriverRefNum;
472 pb->udpStream = stream;
473 pb->ioResult = 1;
474
475 pb->csParam.send.remoteHost = remoteIP;
476 pb->csParam.send.remotePort = remotePort;
477 pb->csParam.send.wdsPtr = (Ptr)wdsPtr;
478 pb->csParam.send.checkSum = 0;
479 pb->csParam.send.sendLength = 0;
480 pb->csParam.send.userDataPtr = userData;
481
482 return PBControl((ParmBlkPtr)pb, async);
483 }
484
485 OSErr
486 _UDPRelease(UDPiopb *pb, StreamPtr stream, Ptr userData,
487 UDPIOCompletionProc ioCompletion, Boolean async)
488 {
489 OSErr osErr;
490
491 memset(pb, 0, sizeof(*pb));
492
493 pb->csCode = UDPRelease;
494 pb->ioCompletion = ioCompletion;
495 pb->ioCRefNum = gIPPDriverRefNum;
496 pb->udpStream = stream;
497 pb->ioResult = 1;
498
499 //pb->csParam.status.userDataPtr = userData;
500
501 osErr = PBControl((ParmBlkPtr)pb, async);
502
503 return osErr;
504 }
505
506
507 /* convenience functions */
508
509 pascal void
510 StrToAddrMarkDone(struct hostInfo *hi, char *data)
511 {
512 volatile int *done = (int *)data;
513 *done = 1;
514 }
515
516 unsigned long
517 ip2long(char *ip)
518 {
519 unsigned long address = 0;
520 short dotcount = 0, i;
521 unsigned short b = 0;
522
523 for (i = 0; ip[i] != 0; i++) {
524 if (ip[i] == '.') {
525 if (++dotcount > 3)
526 return (0);
527 address <<= 8;
528 address |= b;
529 b = 0;
530 } else if (ip[i] >= '0' && ip[i] <= '9') {
531 b *= 10;
532 b += (ip[i] - '0');
533 if (b > 255)
534 return (0);
535 } else
536 return (0);
537 }
538
539 if (dotcount != 3)
540 return (0);
541 address <<= 8;
542 address |= b;
543 return address;
544 }
545
546 void
547 long2ip(unsigned long num, char *ip)
548 {
549 unsigned char *tmp = (unsigned char *)&num;
550 sprintf(ip, "%d.%d.%d.%d", tmp[0], tmp[1], tmp[2], tmp[3]);
551 }
552
553 #define SOCKS_VERSION_SOCKS5 0x5
554 #define SOCKS_METHOD_AUTH_NONE 0x0
555 #define SOCKS_REQUEST_CONNECT 0x1
556 #define SOCKS_REQUEST_ATYP_DOMAINNAME 0x3
557 #define SOCKS_REPLY_SUCCESS 0x0
558
559 OSErr
560 SOCKS5TCPActiveOpen(TCPiopb *pb, StreamPtr stream, ip_addr socks_ip,
561 tcp_port socks_port, char *remote_host, tcp_port remote_port,
562 ip_addr *local_ip, tcp_port *local_port, Ptr user_data,
563 TCPIOCompletionProc io_completion, Boolean async)
564 {
565 OSErr err;
566 TCPStatusPB status_pb;
567 wdsEntry wds[2];
568 char data[255] = { 0 };
569 unsigned short len, remote_host_len;
570
571 remote_host_len = strlen(remote_host);
572 if (remote_host_len + 7 > sizeof(data))
573 return -1;
574
575 err = _TCPActiveOpen(pb, stream, socks_ip, socks_port, local_ip,
576 local_port, user_data, io_completion, async);
577 if (err != noErr)
578 return err;
579
580 data[0] = SOCKS_VERSION_SOCKS5;
581 data[1] = 1; /* nmethods */
582 data[2] = SOCKS_METHOD_AUTH_NONE;
583
584 memset(&wds, 0, sizeof(wds));
585 wds[0].ptr = (Ptr)&data;
586 wds[0].length = 3;
587
588 err = _TCPSend(pb, stream, wds, nil, nil, false);
589 if (err)
590 goto fail;
591
592 for (;;) {
593 err = _TCPStatus(pb, stream, &status_pb, nil, nil, false);
594 if (err != noErr)
595 goto fail;
596
597 if (status_pb.amtUnreadData >= 2)
598 break;
599 }
600
601 len = 2;
602 err = _TCPRcv(pb, stream, (Ptr)&data, &len, nil, nil, false);
603 if (err != noErr)
604 goto fail;
605
606 if (data[0] != SOCKS_VERSION_SOCKS5 || data[1] != SOCKS_METHOD_AUTH_NONE)
607 goto fail;
608
609 len = 0;
610 data[len++] = SOCKS_VERSION_SOCKS5;
611 data[len++] = SOCKS_REQUEST_CONNECT;
612 data[len++] = 0; /* reserved */
613 data[len++] = SOCKS_REQUEST_ATYP_DOMAINNAME;
614 data[len++] = remote_host_len;
615 memcpy(data + len, remote_host, remote_host_len);
616 len += remote_host_len;
617 data[len++] = (remote_port >> 8);
618 data[len++] = (remote_port & 0xff);
619
620 memset(&wds, 0, sizeof(wds));
621 wds[0].ptr = (Ptr)&data;
622 wds[0].length = len;
623
624 err = _TCPSend(pb, stream, wds, nil, nil, false);
625 if (err)
626 goto fail;
627
628 for (;;) {
629 err = _TCPStatus(pb, stream, &status_pb, nil, nil, false);
630 if (err != noErr)
631 goto fail;
632
633 if (status_pb.amtUnreadData >= 7)
634 break;
635 }
636
637 len = status_pb.amtUnreadData;
638 if (len > sizeof(data))
639 len = sizeof(data);
640 err = _TCPRcv(pb, stream, (Ptr)&data, &len, nil, nil, false);
641 if (err != noErr)
642 goto fail;
643
644 if (data[0] != SOCKS_VERSION_SOCKS5 || data[1] != SOCKS_REPLY_SUCCESS)
645 goto fail;
646
647 return noErr;
648
649 fail:
650 _TCPClose(pb, stream, nil, nil, false);
651 return err;
652 }