AmendHub

Download

jcs

/

subtext

/

tcp.c

 

(View History)

jcs   tcp: Don't bother manually zeroing open options Latest amendment: 222 on 2022-07-24

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