bug fix.
[openssl.git] / apps / s_socket.c
index 810061e29fb1e537b9cecc15890244fefc9f7393..888b66df18ea1d9e8a7ed05fb11f94abe6a67877 100644 (file)
@@ -1,5 +1,5 @@
 /* apps/s_socket.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
 #include <string.h>
 #include <errno.h>
 #include <signal.h>
+
+/* With IPv6, it looks like Digital has mixed up the proper order of
+   recursive header file inclusion, resulting in the compiler complaining
+   that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which
+   is needed to have fileno() declared correctly...  So let's define u_int */
+#if defined(VMS) && defined(__DECC) && !defined(__U_INT)
+#define __U_INT
+typedef unsigned int u_int;
+#endif
+
 #define USE_SOCKETS
 #define NON_MAIN
 #include "apps.h"
 #undef USE_SOCKETS
 #undef NON_MAIN
 #include "s_apps.h"
-#include "ssl.h"
+#include <openssl/ssl.h>
 
-#ifndef NOPROTO
-static struct hostent *GetHostByName(char *name);
-int sock_init(void );
-#else
-static struct hostent *GetHostByName();
-int sock_init();
+#ifdef VMS
+#if (__VMS_VER < 70000000) /* FIONBIO used as a switch to enable ioctl,
+                             and that isn't in VMS < 7.0 */
+#undef FIONBIO
+#endif
+#include <processes.h> /* for vfork() */
 #endif
 
+static struct hostent *GetHostByName(char *name);
+int sock_init(void );
 #ifdef WIN16
 #define SOCKET_PROTOCOL        0 /* more microsoft stupidity */
 #else
@@ -93,11 +105,8 @@ static FARPROC lpTopWndProc=NULL;
 static FARPROC lpTopHookProc=NULL;
 extern HINSTANCE _hInstance;  /* nice global CRT provides */
 
-static LONG FAR PASCAL topHookProc(hwnd,message,wParam,lParam)
-HWND hwnd;
-UINT message;
-WPARAM wParam;
-LPARAM lParam;
+static LONG FAR PASCAL topHookProc(HWND hwnd, UINT message, WPARAM wParam,
+            LPARAM lParam)
        {
        if (hwnd == topWnd)
                {
@@ -122,7 +131,7 @@ static BOOL CALLBACK enumproc(HWND hwnd,LPARAM lParam)
 #endif /* WIN32 */
 #endif /* WINDOWS */
 
-void sock_cleanup()
+void sock_cleanup(void)
        {
 #ifdef WINDOWS
        if (wsa_init_done)
@@ -134,7 +143,7 @@ void sock_cleanup()
 #endif
        }
 
-int sock_init()
+int sock_init(void)
        {
 #ifdef WINDOWS
        if (!wsa_init_done)
@@ -165,10 +174,7 @@ int sock_init()
        return(1);
        }
 
-int init_client(sock, host, port)
-int *sock;
-char *host;
-int port;
+int init_client(int *sock, char *host, int port)
        {
        unsigned char ip[4];
        short p=0;
@@ -181,10 +187,7 @@ int port;
        return(init_client_ip(sock,ip,port));
        }
 
-int init_client_ip(sock, ip, port)
-int *sock;
-unsigned char ip[4];
-int port;
+int init_client_ip(int *sock, unsigned char ip[4], int port)
        {
        unsigned long addr;
        struct sockaddr_in them;
@@ -215,23 +218,25 @@ int port;
        return(1);
        }
 
-int nbio_sock_error(sock)
-int sock;
+int nbio_sock_error(int sock)
        {
-       int j,i,size;
+       int j,i;
+       int size;
 
        size=sizeof(int);
-       i=getsockopt(sock,SOL_SOCKET,SO_ERROR,(char *)&j,&size);
+       /* Note: under VMS with SOCKETSHR the third parameter is currently
+        * of type (int *) whereas under other systems it is (void *) if
+        * you don't have a cast it will choke the compiler: if you do
+        * have a cast then you can either go for (int *) or (void *).
+        */
+       i=getsockopt(sock,SOL_SOCKET,SO_ERROR,(char *)&j,(void *)&size);
        if (i < 0)
                return(1);
        else
                return(j);
        }
 
-int nbio_init_client_ip(sock, ip, port)
-int *sock;
-unsigned char ip[4];
-int port;
+int nbio_init_client_ip(int *sock, unsigned char ip[4], int port)
        {
        unsigned long addr;
        struct sockaddr_in them;
@@ -251,7 +256,9 @@ int port;
 
        if (*sock <= 0)
                {
+#ifdef FIONBIO
                unsigned long l=1;
+#endif
 
                s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
                if (s == INVALID_SOCKET) { perror("socket"); return(0); }
@@ -262,7 +269,7 @@ int port;
                *sock=s;
 
 #ifdef FIONBIO
-               socket_ioctl(s,FIONBIO,&l);
+               BIO_socket_ioctl(s,FIONBIO,&l);
 #endif
                }
        else
@@ -280,10 +287,7 @@ int port;
                return(1);
        }
 
-int do_server(port, ret, cb)
-int port;
-int *ret;
-int (*cb)();
+int do_server(int port, int *ret, int (*cb)(), char *context)
        {
        int sock;
        char *name;
@@ -304,20 +308,18 @@ int (*cb)();
                        SHUTDOWN(accept_socket);
                        return(0);
                        }
-               i=(*cb)(name,sock);
+               i=(*cb)(name,sock, context);
                if (name != NULL) Free(name);
-               SHUTDOWN(sock);
+               SHUTDOWN2(sock);
                if (i < 0)
                        {
-                       SHUTDOWN(accept_socket);
+                       SHUTDOWN2(accept_socket);
                        return(i);
                        }
                }
        }
 
-int init_server(sock, port)
-int *sock;
-int port;
+int init_server_long(int *sock, int port, char *ip)
        {
        int ret=0;
        struct sockaddr_in server;
@@ -328,10 +330,25 @@ int port;
        memset((char *)&server,0,sizeof(server));
        server.sin_family=AF_INET;
        server.sin_port=htons((unsigned short)port);
-       server.sin_addr.s_addr=INADDR_ANY;
+       if (ip == NULL)
+               server.sin_addr.s_addr=INADDR_ANY;
+       else
+/* Added for T3E, address-of fails on bit field (beckman@acl.lanl.gov) */
+#ifndef BIT_FIELD_LIMITS
+               memcpy(&server.sin_addr.s_addr,ip,4);
+#else
+               memcpy(&server.sin_addr,ip,4);
+#endif
        s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
 
        if (s == INVALID_SOCKET) goto err;
+#if defined SOL_SOCKET && defined SO_REUSEADDR
+               {
+               int j = 1;
+               setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+                          (void *) &j, sizeof j);
+               }
+#endif
        if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1)
                {
 #ifndef WINDOWS
@@ -339,7 +356,8 @@ int port;
 #endif
                goto err;
                }
-       if (listen(s,5) == -1) goto err;
+       /* Make it 128 for linux */
+       if (listen(s,128) == -1) goto err;
        i=0;
        *sock=s;
        ret=1;
@@ -351,10 +369,12 @@ err:
        return(ret);
        }
 
-int do_accept(acc_sock, sock, host)
-int acc_sock;
-int *sock;
-char **host;
+int init_server(int *sock, int port)
+       {
+       return(init_server_long(sock, port, NULL));
+       }
+
+int do_accept(int acc_sock, int *sock, char **host)
        {
        int ret,i;
        struct hostent *h1,*h2;
@@ -370,7 +390,12 @@ redoit:
 
        memset((char *)&from,0,sizeof(from));
        len=sizeof(from);
-       ret=accept(acc_sock,(struct sockaddr *)&from,&len);
+       /* Note: under VMS with SOCKETSHR the fourth parameter is currently
+        * of type (int *) whereas under other systems it is (void *) if
+        * you don't have a cast it will choke the compiler: if you do
+        * have a cast then you can either go for (int *) or (void *).
+        */
+       ret=accept(acc_sock,(struct sockaddr *)&from,(void *)&len);
        if (ret == INVALID_SOCKET)
                {
 #ifdef WINDOWS
@@ -399,9 +424,14 @@ redoit:
 */
 
        if (host == NULL) goto end;
+#ifndef BIT_FIELD_LIMITS
        /* I should use WSAAsyncGetHostByName() under windows */
        h1=gethostbyaddr((char *)&from.sin_addr.s_addr,
                sizeof(from.sin_addr.s_addr),AF_INET);
+#else
+       h1=gethostbyaddr((char *)&from.sin_addr,
+               sizeof(struct in_addr),AF_INET);
+#endif
        if (h1 == NULL)
                {
                BIO_printf(bio_err,"bad gethostbyaddr\n");
@@ -435,43 +465,8 @@ end:
        return(1);
        }
 
-int socket_ioctl(fd,type,arg)
-int fd;
-long type;
-unsigned long *arg;
-       {
-       int i,err;
-#ifdef WINDOWS
-       i=ioctlsocket(fd,type,arg);
-#else
-       i=ioctl(fd,type,arg);
-#endif
-       if (i < 0)
-               {
-#ifdef WINDOWS
-               err=WSAGetLastError();
-#else
-               err=errno;
-#endif
-               BIO_printf(bio_err,"ioctl on socket failed:error %d\n",err);
-               }
-       return(i);
-       }
-
-int sock_err()
-       {
-#ifdef WINDOWS
-       return(WSAGetLastError());
-#else
-       return(errno);
-#endif
-       }
-
-int extract_host_port(str,host_ptr,ip,port_ptr)
-char *str;
-char **host_ptr;
-unsigned char *ip;
-short *port_ptr;
+int extract_host_port(char *str, char **host_ptr, unsigned char *ip,
+            short *port_ptr)
        {
        char *h,*p;
 
@@ -495,14 +490,12 @@ err:
        return(0);
        }
 
-int host_ip(str,ip)
-char *str;
-unsigned char ip[4];
+int host_ip(char *str, unsigned char ip[4])
        {
        unsigned int in[4]; 
        int i;
 
-       if (sscanf(str,"%d.%d.%d.%d",&(in[0]),&(in[1]),&(in[2]),&(in[3])) == 4)
+       if (sscanf(str,"%u.%u.%u.%u",&(in[0]),&(in[1]),&(in[2]),&(in[3])) == 4)
                {
                for (i=0; i<4; i++)
                        if (in[i] > 255)
@@ -543,9 +536,7 @@ err:
        return(0);
        }
 
-int extract_port(str,port_ptr)
-char *str;
-short *port_ptr;
+int extract_port(char *str, short *port_ptr)
        {
        int i;
        struct servent *s;
@@ -577,8 +568,7 @@ static struct ghbn_cache_st
 static unsigned long ghbn_hits=0L;
 static unsigned long ghbn_miss=0L;
 
-static struct hostent *GetHostByName(name)
-char *name;
+static struct hostent *GetHostByName(char *name)
        {
        struct hostent *ret;
        int i,lowi=0;
@@ -618,11 +608,7 @@ char *name;
        }
 
 #ifndef MSDOS
-int spawn(argc, argv, in, out)
-int argc;
-char **argv;
-int *in;
-int *out;
+int spawn(int argc, char **argv, int *in, int *out)
        {
        int pid;
 #define CHILD_READ     p1[0]
@@ -633,7 +619,11 @@ int *out;
 
        if ((pipe(p1) < 0) || (pipe(p2) < 0)) return(-1);
 
+#ifdef VMS
+       if ((pid=vfork()) == 0)
+#else
        if ((pid=fork()) == 0)
+#endif
                { /* child */
                if (dup2(CHILD_WRITE,fileno(stdout)) < 0)
                        perror("dup2");