Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/openssl/apps/lib/vms_term_sock.c
105911 views
1
/*
2
* Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
3
* Copyright 2016 VMS Software, Inc. All Rights Reserved.
4
*
5
* Licensed under the Apache License 2.0 (the "License"). You may not use
6
* this file except in compliance with the License. You can obtain a copy
7
* in the file LICENSE in the source distribution or at
8
* https://www.openssl.org/source/license.html
9
*/
10
11
#ifdef __VMS
12
#define OPENSSL_SYS_VMS
13
#pragma message disable DOLLARID
14
15
#include <openssl/opensslconf.h>
16
17
#if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS)
18
/*
19
* On VMS, you need to define this to get the declaration of fileno(). The
20
* value 2 is to make sure no function defined in POSIX-2 is left undefined.
21
*/
22
#define _POSIX_C_SOURCE 2
23
#endif
24
25
#include <stdio.h>
26
27
#undef _POSIX_C_SOURCE
28
29
#include <sys/types.h>
30
#include <sys/socket.h>
31
#include <netinet/in.h>
32
#include <inet.h>
33
#include <unistd.h>
34
#include <string.h>
35
#include <errno.h>
36
#include <starlet.h>
37
#include <iodef.h>
38
#ifdef __alpha
39
#include <iosbdef.h>
40
#else
41
typedef struct _iosb { /* Copied from IOSBDEF.H for Alpha */
42
#pragma __nomember_alignment
43
__union
44
{
45
__struct
46
{
47
unsigned short int iosb$w_status; /* Final I/O status */
48
__union
49
{
50
__struct
51
{ /* 16-bit byte count variant */
52
unsigned short int iosb$w_bcnt; /* 16-bit byte count */
53
__union
54
{
55
unsigned int iosb$l_dev_depend; /* 32-bit device dependent info */
56
unsigned int iosb$l_pid; /* 32-bit pid */
57
}
58
iosb$r_l;
59
}
60
iosb$r_bcnt_16;
61
__struct
62
{ /* 32-bit byte count variant */
63
unsigned int iosb$l_bcnt; /* 32-bit byte count (unaligned) */
64
unsigned short int iosb$w_dev_depend_high; /* 16-bit device dependent info */
65
}
66
iosb$r_bcnt_32;
67
}
68
iosb$r_devdepend;
69
}
70
iosb$r_io_64;
71
__struct
72
{
73
__union
74
{
75
unsigned int iosb$l_getxxi_status; /* Final GETxxI status */
76
unsigned int iosb$l_reg_status; /* Final $Registry status */
77
}
78
iosb$r_l_status;
79
unsigned int iosb$l_reserved; /* Reserved field */
80
}
81
iosb$r_get_64;
82
}
83
iosb$r_io_get;
84
} IOSB;
85
86
#if !defined(__VAXC)
87
#define iosb$w_status iosb$r_io_get.iosb$r_io_64.iosb$w_status
88
#define iosb$w_bcnt iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_16.iosb$w_bcnt
89
#define iosb$r_l iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_16.iosb$r_l
90
#define iosb$l_dev_depend iosb$r_l.iosb$l_dev_depend
91
#define iosb$l_pid iosb$r_l.iosb$l_pid
92
#define iosb$l_bcnt iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_32.iosb$l_bcnt
93
#define iosb$w_dev_depend_high iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_32.iosb$w_dev_depend_high
94
#define iosb$l_getxxi_status iosb$r_io_get.iosb$r_get_64.iosb$r_l_status.iosb$l_getxxi_status
95
#define iosb$l_reg_status iosb$r_io_get.iosb$r_get_64.iosb$r_l_status.iosb$l_reg_status
96
#endif /* #if !defined(__VAXC) */
97
98
#endif /* End of IOSBDEF */
99
100
#include <efndef.h>
101
#include <stdlib.h>
102
#include <ssdef.h>
103
#include <time.h>
104
#include <stdarg.h>
105
#include <descrip.h>
106
107
#include "vms_term_sock.h"
108
109
#ifdef __alpha
110
static struct _iosb TerminalDeviceIosb;
111
#else
112
IOSB TerminalDeviceIosb;
113
#endif
114
115
static char TerminalDeviceBuff[255 + 2];
116
static int TerminalSocketPair[2] = { 0, 0 };
117
static unsigned short TerminalDeviceChan = 0;
118
119
static int CreateSocketPair(int, int, int, int *);
120
static void SocketPairTimeoutAst(int);
121
static int TerminalDeviceAst(int);
122
static void LogMessage(char *, ...);
123
124
/*
125
** Socket Pair Timeout Value (must be 0-59 seconds)
126
*/
127
#define SOCKET_PAIR_TIMEOUT_VALUE 20
128
129
/*
130
** Socket Pair Timeout Block which is passed to timeout AST
131
*/
132
typedef struct _SocketPairTimeoutBlock {
133
unsigned short SockChan1;
134
unsigned short SockChan2;
135
} SPTB;
136
137
#ifdef TERM_SOCK_TEST
138
139
/*----------------------------------------------------------------------------*/
140
/* */
141
/*----------------------------------------------------------------------------*/
142
int main(int argc, char *argv[], char *envp[])
143
{
144
char TermBuff[80];
145
int TermSock,
146
status,
147
len;
148
149
LogMessage("Enter 'q' or 'Q' to quit ...");
150
while (OPENSSL_strcasecmp(TermBuff, "Q")) {
151
/*
152
** Create the terminal socket
153
*/
154
status = TerminalSocket(TERM_SOCK_CREATE, &TermSock);
155
if (status != TERM_SOCK_SUCCESS)
156
exit(1);
157
158
/*
159
** Process the terminal input
160
*/
161
LogMessage("Waiting on terminal I/O ...\n");
162
len = recv(TermSock, TermBuff, sizeof(TermBuff), 0);
163
TermBuff[len] = '\0';
164
LogMessage("Received terminal I/O [%s]", TermBuff);
165
166
/*
167
** Delete the terminal socket
168
*/
169
status = TerminalSocket(TERM_SOCK_DELETE, &TermSock);
170
if (status != TERM_SOCK_SUCCESS)
171
exit(1);
172
}
173
174
return 1;
175
}
176
#endif
177
178
/*----------------------------------------------------------------------------*/
179
/* */
180
/*----------------------------------------------------------------------------*/
181
int TerminalSocket(int FunctionCode, int *ReturnSocket)
182
{
183
int status;
184
$DESCRIPTOR(TerminalDeviceDesc, "SYS$COMMAND");
185
186
/*
187
** Process the requested function code
188
*/
189
switch (FunctionCode) {
190
case TERM_SOCK_CREATE:
191
/*
192
** Create a socket pair
193
*/
194
status = CreateSocketPair(AF_INET, SOCK_STREAM, 0, TerminalSocketPair);
195
if (status == -1) {
196
LogMessage("TerminalSocket: CreateSocketPair () - %08X", status);
197
if (TerminalSocketPair[0])
198
close(TerminalSocketPair[0]);
199
if (TerminalSocketPair[1])
200
close(TerminalSocketPair[1]);
201
return TERM_SOCK_FAILURE;
202
}
203
204
/*
205
** Assign a channel to the terminal device
206
*/
207
status = sys$assign(&TerminalDeviceDesc,
208
&TerminalDeviceChan,
209
0, 0, 0);
210
if (!(status & 1)) {
211
LogMessage("TerminalSocket: SYS$ASSIGN () - %08X", status);
212
close(TerminalSocketPair[0]);
213
close(TerminalSocketPair[1]);
214
return TERM_SOCK_FAILURE;
215
}
216
217
/*
218
** Queue an async IO to the terminal device
219
*/
220
status = sys$qio(EFN$C_ENF,
221
TerminalDeviceChan,
222
IO$_READVBLK,
223
&TerminalDeviceIosb,
224
TerminalDeviceAst,
225
0,
226
TerminalDeviceBuff,
227
sizeof(TerminalDeviceBuff) - 2,
228
0, 0, 0, 0);
229
if (!(status & 1)) {
230
LogMessage("TerminalSocket: SYS$QIO () - %08X", status);
231
close(TerminalSocketPair[0]);
232
close(TerminalSocketPair[1]);
233
return TERM_SOCK_FAILURE;
234
}
235
236
/*
237
** Return the input side of the socket pair
238
*/
239
*ReturnSocket = TerminalSocketPair[1];
240
break;
241
242
case TERM_SOCK_DELETE:
243
/*
244
** Cancel any pending IO on the terminal channel
245
*/
246
status = sys$cancel(TerminalDeviceChan);
247
if (!(status & 1)) {
248
LogMessage("TerminalSocket: SYS$CANCEL () - %08X", status);
249
close(TerminalSocketPair[0]);
250
close(TerminalSocketPair[1]);
251
return TERM_SOCK_FAILURE;
252
}
253
254
/*
255
** Deassign the terminal channel
256
*/
257
status = sys$dassgn(TerminalDeviceChan);
258
if (!(status & 1)) {
259
LogMessage("TerminalSocket: SYS$DASSGN () - %08X", status);
260
close(TerminalSocketPair[0]);
261
close(TerminalSocketPair[1]);
262
return TERM_SOCK_FAILURE;
263
}
264
265
/*
266
** Close the terminal socket pair
267
*/
268
close(TerminalSocketPair[0]);
269
close(TerminalSocketPair[1]);
270
271
/*
272
** Return the initialized socket
273
*/
274
*ReturnSocket = 0;
275
break;
276
277
default:
278
/*
279
** Invalid function code
280
*/
281
LogMessage("TerminalSocket: Invalid Function Code - %d", FunctionCode);
282
return TERM_SOCK_FAILURE;
283
break;
284
}
285
286
/*
287
** Return success
288
*/
289
return TERM_SOCK_SUCCESS;
290
}
291
292
/*----------------------------------------------------------------------------*/
293
/* */
294
/*----------------------------------------------------------------------------*/
295
static int CreateSocketPair(int SocketFamily,
296
int SocketType,
297
int SocketProtocol,
298
int *SocketPair)
299
{
300
struct dsc$descriptor AscTimeDesc = { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };
301
static const char *LocalHostAddr = { "127.0.0.1" };
302
unsigned short TcpAcceptChan = 0,
303
TcpDeviceChan = 0;
304
unsigned long BinTimeBuff[2];
305
struct sockaddr_in sin;
306
char AscTimeBuff[32];
307
short LocalHostPort;
308
int status;
309
unsigned int slen;
310
311
#ifdef __alpha
312
struct _iosb iosb;
313
#else
314
IOSB iosb;
315
#endif
316
317
int SockDesc1 = 0,
318
SockDesc2 = 0;
319
SPTB sptb;
320
$DESCRIPTOR(TcpDeviceDesc, "TCPIP$DEVICE");
321
322
/*
323
** Create a socket
324
*/
325
SockDesc1 = socket(SocketFamily, SocketType, 0);
326
if (SockDesc1 < 0) {
327
LogMessage("CreateSocketPair: socket () - %d", errno);
328
return -1;
329
}
330
331
/*
332
** Initialize the socket information
333
*/
334
slen = sizeof(sin);
335
memset((char *)&sin, 0, slen);
336
sin.sin_family = SocketFamily;
337
sin.sin_addr.s_addr = inet_addr(LocalHostAddr);
338
sin.sin_port = 0;
339
340
/*
341
** Bind the socket to the local IP
342
*/
343
status = bind(SockDesc1, (struct sockaddr *)&sin, slen);
344
if (status < 0) {
345
LogMessage("CreateSocketPair: bind () - %d", errno);
346
close(SockDesc1);
347
return -1;
348
}
349
350
/*
351
** Get the socket name so we can save the port number
352
*/
353
status = getsockname(SockDesc1, (struct sockaddr *)&sin, &slen);
354
if (status < 0) {
355
LogMessage("CreateSocketPair: getsockname () - %d", errno);
356
close(SockDesc1);
357
return -1;
358
} else
359
LocalHostPort = sin.sin_port;
360
361
/*
362
** Setup a listen for the socket
363
*/
364
listen(SockDesc1, 5);
365
366
/*
367
** Get the binary (64-bit) time of the specified timeout value
368
*/
369
BIO_snprintf(AscTimeBuff, sizeof(AscTimeBuff), "0 0:0:%02d.00", SOCKET_PAIR_TIMEOUT_VALUE);
370
AscTimeDesc.dsc$w_length = strlen(AscTimeBuff);
371
AscTimeDesc.dsc$a_pointer = AscTimeBuff;
372
status = sys$bintim(&AscTimeDesc, BinTimeBuff);
373
if (!(status & 1)) {
374
LogMessage("CreateSocketPair: SYS$BINTIM () - %08X", status);
375
close(SockDesc1);
376
return -1;
377
}
378
379
/*
380
** Assign another channel to the TCP/IP device for the accept.
381
** This is the channel that ends up being connected to.
382
*/
383
status = sys$assign(&TcpDeviceDesc, &TcpDeviceChan, 0, 0, 0);
384
if (!(status & 1)) {
385
LogMessage("CreateSocketPair: SYS$ASSIGN () - %08X", status);
386
close(SockDesc1);
387
return -1;
388
}
389
390
/*
391
** Get the channel of the first socket for the accept
392
*/
393
TcpAcceptChan = decc$get_sdc(SockDesc1);
394
395
/*
396
** Perform the accept using $QIO so we can do this asynchronously
397
*/
398
status = sys$qio(EFN$C_ENF,
399
TcpAcceptChan,
400
IO$_ACCESS | IO$M_ACCEPT,
401
&iosb,
402
0, 0, 0, 0, 0,
403
&TcpDeviceChan,
404
0, 0);
405
if (!(status & 1)) {
406
LogMessage("CreateSocketPair: SYS$QIO () - %08X", status);
407
close(SockDesc1);
408
sys$dassgn(TcpDeviceChan);
409
return -1;
410
}
411
412
/*
413
** Create the second socket to do the connect
414
*/
415
SockDesc2 = socket(SocketFamily, SocketType, 0);
416
if (SockDesc2 < 0) {
417
LogMessage("CreateSocketPair: socket () - %d", errno);
418
sys$cancel(TcpAcceptChan);
419
close(SockDesc1);
420
sys$dassgn(TcpDeviceChan);
421
return (-1);
422
}
423
424
/*
425
** Setup the Socket Pair Timeout Block
426
*/
427
sptb.SockChan1 = TcpAcceptChan;
428
sptb.SockChan2 = decc$get_sdc(SockDesc2);
429
430
/*
431
** Before we block on the connect, set a timer that can cancel I/O on our
432
** two sockets if it never connects.
433
*/
434
status = sys$setimr(EFN$C_ENF,
435
BinTimeBuff,
436
SocketPairTimeoutAst,
437
&sptb,
438
0);
439
if (!(status & 1)) {
440
LogMessage("CreateSocketPair: SYS$SETIMR () - %08X", status);
441
sys$cancel(TcpAcceptChan);
442
close(SockDesc1);
443
close(SockDesc2);
444
sys$dassgn(TcpDeviceChan);
445
return -1;
446
}
447
448
/*
449
** Now issue the connect
450
*/
451
memset((char *)&sin, 0, sizeof(sin));
452
sin.sin_family = SocketFamily;
453
sin.sin_addr.s_addr = inet_addr(LocalHostAddr);
454
sin.sin_port = LocalHostPort;
455
456
status = connect(SockDesc2, (struct sockaddr *)&sin, sizeof(sin));
457
if (status < 0) {
458
LogMessage("CreateSocketPair: connect () - %d", errno);
459
sys$cantim(&sptb, 0);
460
sys$cancel(TcpAcceptChan);
461
close(SockDesc1);
462
close(SockDesc2);
463
sys$dassgn(TcpDeviceChan);
464
return -1;
465
}
466
467
/*
468
** Wait for the asynch $QIO to finish. Note that if the I/O was aborted
469
** (SS$_ABORT), then we probably canceled it from the AST routine - so log
470
** a timeout.
471
*/
472
status = sys$synch(EFN$C_ENF, &iosb);
473
if (!(iosb.iosb$w_status & 1)) {
474
if (iosb.iosb$w_status == SS$_ABORT)
475
LogMessage("CreateSocketPair: SYS$QIO(iosb) timeout");
476
else {
477
LogMessage("CreateSocketPair: SYS$QIO(iosb) - %d",
478
iosb.iosb$w_status);
479
sys$cantim(&sptb, 0);
480
}
481
close(SockDesc1);
482
close(SockDesc2);
483
sys$dassgn(TcpDeviceChan);
484
return -1;
485
}
486
487
/*
488
** Here we're successfully connected, so cancel the timer, convert the
489
** I/O channel to a socket fd, close the listener socket and return the
490
** connected pair.
491
*/
492
sys$cantim(&sptb, 0);
493
494
close(SockDesc1);
495
SocketPair[0] = SockDesc2;
496
SocketPair[1] = socket_fd(TcpDeviceChan);
497
498
return (0);
499
}
500
501
/*----------------------------------------------------------------------------*/
502
/* */
503
/*----------------------------------------------------------------------------*/
504
static void SocketPairTimeoutAst(int astparm)
505
{
506
SPTB *sptb = (SPTB *)astparm;
507
508
sys$cancel(sptb->SockChan2); /* Cancel the connect() */
509
sys$cancel(sptb->SockChan1); /* Cancel the accept() */
510
511
return;
512
}
513
514
/*----------------------------------------------------------------------------*/
515
/* */
516
/*----------------------------------------------------------------------------*/
517
static int TerminalDeviceAst(int astparm)
518
{
519
int status;
520
521
/*
522
** Terminate the terminal buffer
523
*/
524
TerminalDeviceBuff[TerminalDeviceIosb.iosb$w_bcnt] = '\0';
525
strcat(TerminalDeviceBuff, "\n");
526
527
/*
528
** Send the data read from the terminal device through the socket pair
529
*/
530
send(TerminalSocketPair[0], TerminalDeviceBuff,
531
TerminalDeviceIosb.iosb$w_bcnt + 1, 0);
532
533
/*
534
** Queue another async IO to the terminal device
535
*/
536
status = sys$qio(EFN$C_ENF,
537
TerminalDeviceChan,
538
IO$_READVBLK,
539
&TerminalDeviceIosb,
540
TerminalDeviceAst,
541
0,
542
TerminalDeviceBuff,
543
sizeof(TerminalDeviceBuff) - 2,
544
0, 0, 0, 0);
545
546
/*
547
** Return status
548
*/
549
return status;
550
}
551
552
/*----------------------------------------------------------------------------*/
553
/* */
554
/*----------------------------------------------------------------------------*/
555
static void LogMessage(char *msg, ...)
556
{
557
char *Month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
558
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
559
static unsigned int pid = 0;
560
va_list args;
561
time_t CurTime;
562
struct tm *LocTime;
563
char MsgBuff[256];
564
565
/*
566
** Get the process pid
567
*/
568
if (pid == 0)
569
pid = getpid();
570
571
/*
572
** Convert the current time into local time
573
*/
574
CurTime = time(NULL);
575
LocTime = localtime(&CurTime);
576
577
/*
578
** Format the message buffer
579
*/
580
BIO_snprintf(MsgBuff, sizeof(MsgBuff), "%02d-%s-%04d %02d:%02d:%02d [%08X] %s\n",
581
LocTime->tm_mday, Month[LocTime->tm_mon],
582
(LocTime->tm_year + 1900), LocTime->tm_hour, LocTime->tm_min,
583
LocTime->tm_sec, pid, msg);
584
585
/*
586
** Get any variable arguments and add them to the print of the message
587
** buffer
588
*/
589
va_start(args, msg);
590
vfprintf(stderr, MsgBuff, args);
591
va_end(args);
592
593
/*
594
** Flush standard error output
595
*/
596
fsync(fileno(stderr));
597
598
return;
599
}
600
#endif
601
602