AmendHub

Download

jcs

/

wikipedia

/

tcp.c

 

(View History)

jcs   *: Import skeleton code Latest amendment: 1 on 2022-08-18

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