Path: blob/main/crypto/openssl/apps/lib/vms_term_sock.c
105911 views
/*1* Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.2* Copyright 2016 VMS Software, Inc. All Rights Reserved.3*4* Licensed under the Apache License 2.0 (the "License"). You may not use5* this file except in compliance with the License. You can obtain a copy6* in the file LICENSE in the source distribution or at7* https://www.openssl.org/source/license.html8*/910#ifdef __VMS11#define OPENSSL_SYS_VMS12#pragma message disable DOLLARID1314#include <openssl/opensslconf.h>1516#if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS)17/*18* On VMS, you need to define this to get the declaration of fileno(). The19* value 2 is to make sure no function defined in POSIX-2 is left undefined.20*/21#define _POSIX_C_SOURCE 222#endif2324#include <stdio.h>2526#undef _POSIX_C_SOURCE2728#include <sys/types.h>29#include <sys/socket.h>30#include <netinet/in.h>31#include <inet.h>32#include <unistd.h>33#include <string.h>34#include <errno.h>35#include <starlet.h>36#include <iodef.h>37#ifdef __alpha38#include <iosbdef.h>39#else40typedef struct _iosb { /* Copied from IOSBDEF.H for Alpha */41#pragma __nomember_alignment42__union43{44__struct45{46unsigned short int iosb$w_status; /* Final I/O status */47__union48{49__struct50{ /* 16-bit byte count variant */51unsigned short int iosb$w_bcnt; /* 16-bit byte count */52__union53{54unsigned int iosb$l_dev_depend; /* 32-bit device dependent info */55unsigned int iosb$l_pid; /* 32-bit pid */56}57iosb$r_l;58}59iosb$r_bcnt_16;60__struct61{ /* 32-bit byte count variant */62unsigned int iosb$l_bcnt; /* 32-bit byte count (unaligned) */63unsigned short int iosb$w_dev_depend_high; /* 16-bit device dependent info */64}65iosb$r_bcnt_32;66}67iosb$r_devdepend;68}69iosb$r_io_64;70__struct71{72__union73{74unsigned int iosb$l_getxxi_status; /* Final GETxxI status */75unsigned int iosb$l_reg_status; /* Final $Registry status */76}77iosb$r_l_status;78unsigned int iosb$l_reserved; /* Reserved field */79}80iosb$r_get_64;81}82iosb$r_io_get;83} IOSB;8485#if !defined(__VAXC)86#define iosb$w_status iosb$r_io_get.iosb$r_io_64.iosb$w_status87#define iosb$w_bcnt iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_16.iosb$w_bcnt88#define iosb$r_l iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_16.iosb$r_l89#define iosb$l_dev_depend iosb$r_l.iosb$l_dev_depend90#define iosb$l_pid iosb$r_l.iosb$l_pid91#define iosb$l_bcnt iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_32.iosb$l_bcnt92#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_high93#define iosb$l_getxxi_status iosb$r_io_get.iosb$r_get_64.iosb$r_l_status.iosb$l_getxxi_status94#define iosb$l_reg_status iosb$r_io_get.iosb$r_get_64.iosb$r_l_status.iosb$l_reg_status95#endif /* #if !defined(__VAXC) */9697#endif /* End of IOSBDEF */9899#include <efndef.h>100#include <stdlib.h>101#include <ssdef.h>102#include <time.h>103#include <stdarg.h>104#include <descrip.h>105106#include "vms_term_sock.h"107108#ifdef __alpha109static struct _iosb TerminalDeviceIosb;110#else111IOSB TerminalDeviceIosb;112#endif113114static char TerminalDeviceBuff[255 + 2];115static int TerminalSocketPair[2] = { 0, 0 };116static unsigned short TerminalDeviceChan = 0;117118static int CreateSocketPair(int, int, int, int *);119static void SocketPairTimeoutAst(int);120static int TerminalDeviceAst(int);121static void LogMessage(char *, ...);122123/*124** Socket Pair Timeout Value (must be 0-59 seconds)125*/126#define SOCKET_PAIR_TIMEOUT_VALUE 20127128/*129** Socket Pair Timeout Block which is passed to timeout AST130*/131typedef struct _SocketPairTimeoutBlock {132unsigned short SockChan1;133unsigned short SockChan2;134} SPTB;135136#ifdef TERM_SOCK_TEST137138/*----------------------------------------------------------------------------*/139/* */140/*----------------------------------------------------------------------------*/141int main(int argc, char *argv[], char *envp[])142{143char TermBuff[80];144int TermSock,145status,146len;147148LogMessage("Enter 'q' or 'Q' to quit ...");149while (OPENSSL_strcasecmp(TermBuff, "Q")) {150/*151** Create the terminal socket152*/153status = TerminalSocket(TERM_SOCK_CREATE, &TermSock);154if (status != TERM_SOCK_SUCCESS)155exit(1);156157/*158** Process the terminal input159*/160LogMessage("Waiting on terminal I/O ...\n");161len = recv(TermSock, TermBuff, sizeof(TermBuff), 0);162TermBuff[len] = '\0';163LogMessage("Received terminal I/O [%s]", TermBuff);164165/*166** Delete the terminal socket167*/168status = TerminalSocket(TERM_SOCK_DELETE, &TermSock);169if (status != TERM_SOCK_SUCCESS)170exit(1);171}172173return 1;174}175#endif176177/*----------------------------------------------------------------------------*/178/* */179/*----------------------------------------------------------------------------*/180int TerminalSocket(int FunctionCode, int *ReturnSocket)181{182int status;183$DESCRIPTOR(TerminalDeviceDesc, "SYS$COMMAND");184185/*186** Process the requested function code187*/188switch (FunctionCode) {189case TERM_SOCK_CREATE:190/*191** Create a socket pair192*/193status = CreateSocketPair(AF_INET, SOCK_STREAM, 0, TerminalSocketPair);194if (status == -1) {195LogMessage("TerminalSocket: CreateSocketPair () - %08X", status);196if (TerminalSocketPair[0])197close(TerminalSocketPair[0]);198if (TerminalSocketPair[1])199close(TerminalSocketPair[1]);200return TERM_SOCK_FAILURE;201}202203/*204** Assign a channel to the terminal device205*/206status = sys$assign(&TerminalDeviceDesc,207&TerminalDeviceChan,2080, 0, 0);209if (!(status & 1)) {210LogMessage("TerminalSocket: SYS$ASSIGN () - %08X", status);211close(TerminalSocketPair[0]);212close(TerminalSocketPair[1]);213return TERM_SOCK_FAILURE;214}215216/*217** Queue an async IO to the terminal device218*/219status = sys$qio(EFN$C_ENF,220TerminalDeviceChan,221IO$_READVBLK,222&TerminalDeviceIosb,223TerminalDeviceAst,2240,225TerminalDeviceBuff,226sizeof(TerminalDeviceBuff) - 2,2270, 0, 0, 0);228if (!(status & 1)) {229LogMessage("TerminalSocket: SYS$QIO () - %08X", status);230close(TerminalSocketPair[0]);231close(TerminalSocketPair[1]);232return TERM_SOCK_FAILURE;233}234235/*236** Return the input side of the socket pair237*/238*ReturnSocket = TerminalSocketPair[1];239break;240241case TERM_SOCK_DELETE:242/*243** Cancel any pending IO on the terminal channel244*/245status = sys$cancel(TerminalDeviceChan);246if (!(status & 1)) {247LogMessage("TerminalSocket: SYS$CANCEL () - %08X", status);248close(TerminalSocketPair[0]);249close(TerminalSocketPair[1]);250return TERM_SOCK_FAILURE;251}252253/*254** Deassign the terminal channel255*/256status = sys$dassgn(TerminalDeviceChan);257if (!(status & 1)) {258LogMessage("TerminalSocket: SYS$DASSGN () - %08X", status);259close(TerminalSocketPair[0]);260close(TerminalSocketPair[1]);261return TERM_SOCK_FAILURE;262}263264/*265** Close the terminal socket pair266*/267close(TerminalSocketPair[0]);268close(TerminalSocketPair[1]);269270/*271** Return the initialized socket272*/273*ReturnSocket = 0;274break;275276default:277/*278** Invalid function code279*/280LogMessage("TerminalSocket: Invalid Function Code - %d", FunctionCode);281return TERM_SOCK_FAILURE;282break;283}284285/*286** Return success287*/288return TERM_SOCK_SUCCESS;289}290291/*----------------------------------------------------------------------------*/292/* */293/*----------------------------------------------------------------------------*/294static int CreateSocketPair(int SocketFamily,295int SocketType,296int SocketProtocol,297int *SocketPair)298{299struct dsc$descriptor AscTimeDesc = { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };300static const char *LocalHostAddr = { "127.0.0.1" };301unsigned short TcpAcceptChan = 0,302TcpDeviceChan = 0;303unsigned long BinTimeBuff[2];304struct sockaddr_in sin;305char AscTimeBuff[32];306short LocalHostPort;307int status;308unsigned int slen;309310#ifdef __alpha311struct _iosb iosb;312#else313IOSB iosb;314#endif315316int SockDesc1 = 0,317SockDesc2 = 0;318SPTB sptb;319$DESCRIPTOR(TcpDeviceDesc, "TCPIP$DEVICE");320321/*322** Create a socket323*/324SockDesc1 = socket(SocketFamily, SocketType, 0);325if (SockDesc1 < 0) {326LogMessage("CreateSocketPair: socket () - %d", errno);327return -1;328}329330/*331** Initialize the socket information332*/333slen = sizeof(sin);334memset((char *)&sin, 0, slen);335sin.sin_family = SocketFamily;336sin.sin_addr.s_addr = inet_addr(LocalHostAddr);337sin.sin_port = 0;338339/*340** Bind the socket to the local IP341*/342status = bind(SockDesc1, (struct sockaddr *)&sin, slen);343if (status < 0) {344LogMessage("CreateSocketPair: bind () - %d", errno);345close(SockDesc1);346return -1;347}348349/*350** Get the socket name so we can save the port number351*/352status = getsockname(SockDesc1, (struct sockaddr *)&sin, &slen);353if (status < 0) {354LogMessage("CreateSocketPair: getsockname () - %d", errno);355close(SockDesc1);356return -1;357} else358LocalHostPort = sin.sin_port;359360/*361** Setup a listen for the socket362*/363listen(SockDesc1, 5);364365/*366** Get the binary (64-bit) time of the specified timeout value367*/368BIO_snprintf(AscTimeBuff, sizeof(AscTimeBuff), "0 0:0:%02d.00", SOCKET_PAIR_TIMEOUT_VALUE);369AscTimeDesc.dsc$w_length = strlen(AscTimeBuff);370AscTimeDesc.dsc$a_pointer = AscTimeBuff;371status = sys$bintim(&AscTimeDesc, BinTimeBuff);372if (!(status & 1)) {373LogMessage("CreateSocketPair: SYS$BINTIM () - %08X", status);374close(SockDesc1);375return -1;376}377378/*379** Assign another channel to the TCP/IP device for the accept.380** This is the channel that ends up being connected to.381*/382status = sys$assign(&TcpDeviceDesc, &TcpDeviceChan, 0, 0, 0);383if (!(status & 1)) {384LogMessage("CreateSocketPair: SYS$ASSIGN () - %08X", status);385close(SockDesc1);386return -1;387}388389/*390** Get the channel of the first socket for the accept391*/392TcpAcceptChan = decc$get_sdc(SockDesc1);393394/*395** Perform the accept using $QIO so we can do this asynchronously396*/397status = sys$qio(EFN$C_ENF,398TcpAcceptChan,399IO$_ACCESS | IO$M_ACCEPT,400&iosb,4010, 0, 0, 0, 0,402&TcpDeviceChan,4030, 0);404if (!(status & 1)) {405LogMessage("CreateSocketPair: SYS$QIO () - %08X", status);406close(SockDesc1);407sys$dassgn(TcpDeviceChan);408return -1;409}410411/*412** Create the second socket to do the connect413*/414SockDesc2 = socket(SocketFamily, SocketType, 0);415if (SockDesc2 < 0) {416LogMessage("CreateSocketPair: socket () - %d", errno);417sys$cancel(TcpAcceptChan);418close(SockDesc1);419sys$dassgn(TcpDeviceChan);420return (-1);421}422423/*424** Setup the Socket Pair Timeout Block425*/426sptb.SockChan1 = TcpAcceptChan;427sptb.SockChan2 = decc$get_sdc(SockDesc2);428429/*430** Before we block on the connect, set a timer that can cancel I/O on our431** two sockets if it never connects.432*/433status = sys$setimr(EFN$C_ENF,434BinTimeBuff,435SocketPairTimeoutAst,436&sptb,4370);438if (!(status & 1)) {439LogMessage("CreateSocketPair: SYS$SETIMR () - %08X", status);440sys$cancel(TcpAcceptChan);441close(SockDesc1);442close(SockDesc2);443sys$dassgn(TcpDeviceChan);444return -1;445}446447/*448** Now issue the connect449*/450memset((char *)&sin, 0, sizeof(sin));451sin.sin_family = SocketFamily;452sin.sin_addr.s_addr = inet_addr(LocalHostAddr);453sin.sin_port = LocalHostPort;454455status = connect(SockDesc2, (struct sockaddr *)&sin, sizeof(sin));456if (status < 0) {457LogMessage("CreateSocketPair: connect () - %d", errno);458sys$cantim(&sptb, 0);459sys$cancel(TcpAcceptChan);460close(SockDesc1);461close(SockDesc2);462sys$dassgn(TcpDeviceChan);463return -1;464}465466/*467** Wait for the asynch $QIO to finish. Note that if the I/O was aborted468** (SS$_ABORT), then we probably canceled it from the AST routine - so log469** a timeout.470*/471status = sys$synch(EFN$C_ENF, &iosb);472if (!(iosb.iosb$w_status & 1)) {473if (iosb.iosb$w_status == SS$_ABORT)474LogMessage("CreateSocketPair: SYS$QIO(iosb) timeout");475else {476LogMessage("CreateSocketPair: SYS$QIO(iosb) - %d",477iosb.iosb$w_status);478sys$cantim(&sptb, 0);479}480close(SockDesc1);481close(SockDesc2);482sys$dassgn(TcpDeviceChan);483return -1;484}485486/*487** Here we're successfully connected, so cancel the timer, convert the488** I/O channel to a socket fd, close the listener socket and return the489** connected pair.490*/491sys$cantim(&sptb, 0);492493close(SockDesc1);494SocketPair[0] = SockDesc2;495SocketPair[1] = socket_fd(TcpDeviceChan);496497return (0);498}499500/*----------------------------------------------------------------------------*/501/* */502/*----------------------------------------------------------------------------*/503static void SocketPairTimeoutAst(int astparm)504{505SPTB *sptb = (SPTB *)astparm;506507sys$cancel(sptb->SockChan2); /* Cancel the connect() */508sys$cancel(sptb->SockChan1); /* Cancel the accept() */509510return;511}512513/*----------------------------------------------------------------------------*/514/* */515/*----------------------------------------------------------------------------*/516static int TerminalDeviceAst(int astparm)517{518int status;519520/*521** Terminate the terminal buffer522*/523TerminalDeviceBuff[TerminalDeviceIosb.iosb$w_bcnt] = '\0';524strcat(TerminalDeviceBuff, "\n");525526/*527** Send the data read from the terminal device through the socket pair528*/529send(TerminalSocketPair[0], TerminalDeviceBuff,530TerminalDeviceIosb.iosb$w_bcnt + 1, 0);531532/*533** Queue another async IO to the terminal device534*/535status = sys$qio(EFN$C_ENF,536TerminalDeviceChan,537IO$_READVBLK,538&TerminalDeviceIosb,539TerminalDeviceAst,5400,541TerminalDeviceBuff,542sizeof(TerminalDeviceBuff) - 2,5430, 0, 0, 0);544545/*546** Return status547*/548return status;549}550551/*----------------------------------------------------------------------------*/552/* */553/*----------------------------------------------------------------------------*/554static void LogMessage(char *msg, ...)555{556char *Month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",557"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };558static unsigned int pid = 0;559va_list args;560time_t CurTime;561struct tm *LocTime;562char MsgBuff[256];563564/*565** Get the process pid566*/567if (pid == 0)568pid = getpid();569570/*571** Convert the current time into local time572*/573CurTime = time(NULL);574LocTime = localtime(&CurTime);575576/*577** Format the message buffer578*/579BIO_snprintf(MsgBuff, sizeof(MsgBuff), "%02d-%s-%04d %02d:%02d:%02d [%08X] %s\n",580LocTime->tm_mday, Month[LocTime->tm_mon],581(LocTime->tm_year + 1900), LocTime->tm_hour, LocTime->tm_min,582LocTime->tm_sec, pid, msg);583584/*585** Get any variable arguments and add them to the print of the message586** buffer587*/588va_start(args, msg);589vfprintf(stderr, MsgBuff, args);590va_end(args);591592/*593** Flush standard error output594*/595fsync(fileno(stderr));596597return;598}599#endif600601602