AmendHub

Download

jcs

/

subtext

/

tcp.c

 

(View History)

jcs   tcp: Add copyright header Latest amendment: 466 on 2023-04-07

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