AmendHub

Download

vkoskiv

/

MacNTP

/

tcp.c

 

(View History)

vkoskiv   Add copyright headers Latest amendment: 12 on 2023-09-07

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