add -naccept <n> option to s_server to automatically exit after <n> connections
[openssl.git] / apps / s_socket.c
index a88de6c..f73f193 100644 (file)
@@ -62,8 +62,6 @@
 #include <errno.h>
 #include <signal.h>
 
-#include <openssl/e_os2.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
@@ -81,14 +79,27 @@ typedef unsigned int u_int;
 #include "s_apps.h"
 #include <openssl/ssl.h>
 
+#ifdef FLAT_INC
+#include "e_os.h"
+#else
+#include "../e_os.h"
+#endif
+
+#ifndef OPENSSL_NO_SOCK
+
+#if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_BSDSOCK)
+#include "netdb.h"
+#endif
+
 static struct hostent *GetHostByName(char *name);
-#ifdef OPENSSL_SYS_WINDOWS
+#if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK))
 static void ssl_sock_cleanup(void);
 #endif
 static int ssl_sock_init(void);
-static int init_client_ip(int *sock,unsigned char ip[4], int port);
-static int init_server(int *sock, int port);
-static int init_server_long(int *sock, int port,char *ip);
+static int init_client_ip(int *sock, const unsigned char ip[4], int port,
+                         int type);
+static int init_server(int *sock, int port, int type);
+static int init_server_long(int *sock, int port,char *ip, int type);
 static int do_accept(int acc_sock, int *sock, char **host);
 static int host_ip(char *str, unsigned char ip[4]);
 
@@ -98,6 +109,10 @@ static int host_ip(char *str, unsigned char ip[4]);
 #define SOCKET_PROTOCOL        IPPROTO_TCP
 #endif
 
+#if defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
+static int wsa_init_done=0;
+#endif
+
 #ifdef OPENSSL_SYS_WINDOWS
 static struct WSAData wsa_state;
 static int wsa_init_done=0;
@@ -146,6 +161,15 @@ static void ssl_sock_cleanup(void)
                WSACleanup();
                }
        }
+#elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
+static void sock_cleanup(void)
+    {
+    if (wsa_init_done)
+        {
+        wsa_init_done=0;
+               WSACleanup();
+               }
+       }
 #endif
 
 static int ssl_sock_init(void)
@@ -153,7 +177,6 @@ static int ssl_sock_init(void)
 #ifdef WATT32
        extern int _watt_do_exit;
        _watt_do_exit = 0;
-       dbug_init();
        if (sock_init())
                return (0);
 #elif defined(OPENSSL_SYS_WINDOWS)
@@ -181,24 +204,43 @@ static int ssl_sock_init(void)
                SetWindowLong(topWnd,GWL_WNDPROC,(LONG)lpTopHookProc);
 #endif /* OPENSSL_SYS_WIN16 */
                }
+#elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
+   WORD wVerReq;
+   WSADATA wsaData;
+   int err;
+
+   if (!wsa_init_done)
+      {
+   
+# ifdef SIGINT
+      signal(SIGINT,(void (*)(int))sock_cleanup);
+# endif
+
+      wsa_init_done=1;
+      wVerReq = MAKEWORD( 2, 0 );
+      err = WSAStartup(wVerReq,&wsaData);
+      if (err != 0)
+         {
+         BIO_printf(bio_err,"unable to start WINSOCK2, error code=%d\n",err);
+         return(0);
+         }
+      }
 #endif /* OPENSSL_SYS_WINDOWS */
        return(1);
        }
 
-int init_client(int *sock, char *host, int port)
+int init_client(int *sock, char *host, int port, int type)
        {
        unsigned char ip[4];
-       short p=0;
 
+       ip[0] = ip[1] = ip[2] = ip[3] = 0;
        if (!host_ip(host,&(ip[0])))
-               {
-               return(0);
-               }
-       if (p != 0) port=p;
-       return(init_client_ip(sock,ip,port));
+               return 0;
+       return init_client_ip(sock,ip,port,type);
        }
 
-static int init_client_ip(int *sock, unsigned char ip[4], int port)
+static int init_client_ip(int *sock, const unsigned char ip[4], int port,
+                         int type)
        {
        unsigned long addr;
        struct sockaddr_in them;
@@ -216,46 +258,61 @@ static int init_client_ip(int *sock, unsigned char ip[4], int port)
                ((unsigned long)ip[3]);
        them.sin_addr.s_addr=htonl(addr);
 
-       s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
+       if (type == SOCK_STREAM)
+               s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
+       else /* ( type == SOCK_DGRAM) */
+               s=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
+                       
        if (s == INVALID_SOCKET) { perror("socket"); return(0); }
 
-#ifndef OPENSSL_SYS_MPE
-       i=0;
-       i=setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i));
-       if (i < 0) { perror("keepalive"); return(0); }
+#if defined(SO_KEEPALIVE) && !defined(OPENSSL_SYS_MPE)
+       if (type == SOCK_STREAM)
+               {
+               i=0;
+               i=setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i));
+               if (i < 0) { perror("keepalive"); return(0); }
+               }
 #endif
 
        if (connect(s,(struct sockaddr *)&them,sizeof(them)) == -1)
-               { close(s); perror("connect"); return(0); }
+               { closesocket(s); perror("connect"); return(0); }
        *sock=s;
        return(1);
        }
 
-int do_server(int port, int *ret, int (*cb)(), char *context)
+int do_server(int port, int type, int *ret, int (*cb)(char *hostname, int s, unsigned char *context), unsigned char *context, int naccept)
        {
        int sock;
-       char *name;
-       int accept_socket;
+       char *name = NULL;
+       int accept_socket = 0;
        int i;
 
-       if (!init_server(&accept_socket,port)) return(0);
+       if (!init_server(&accept_socket,port,type)) return(0);
 
        if (ret != NULL)
                {
                *ret=accept_socket;
                /* return(1);*/
                }
-       for (;;)
-               {
-               if (do_accept(accept_socket,&sock,&name) == 0)
+       for (;;)
+               {
+               if (type==SOCK_STREAM)
                        {
-                       SHUTDOWN(accept_socket);
-                       return(0);
+                       if (do_accept(accept_socket,&sock,&name) == 0)
+                               {
+                               SHUTDOWN(accept_socket);
+                               return(0);
+                               }
                        }
+               else
+                       sock = accept_socket;
                i=(*cb)(name,sock, context);
                if (name != NULL) OPENSSL_free(name);
-               SHUTDOWN2(sock);
-               if (i < 0)
+               if (type==SOCK_STREAM)
+                       SHUTDOWN2(sock);
+               if (naccept != -1)
+                       naccept--;
+               if (i < 0 || naccept == 0)
                        {
                        SHUTDOWN2(accept_socket);
                        return(i);
@@ -263,11 +320,11 @@ int do_server(int port, int *ret, int (*cb)(), char *context)
                }
        }
 
-static int init_server_long(int *sock, int port, char *ip)
+static int init_server_long(int *sock, int port, char *ip, int type)
        {
        int ret=0;
        struct sockaddr_in server;
-       int s= -1,i;
+       int s= -1;
 
        if (!ssl_sock_init()) return(0);
 
@@ -283,7 +340,11 @@ static int init_server_long(int *sock, int port, char *ip)
 #else
                memcpy(&server.sin_addr,ip,4);
 #endif
-       s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
+       
+               if (type == SOCK_STREAM)
+                       s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
+               else /* type == SOCK_DGRAM */
+                       s=socket(AF_INET, SOCK_DGRAM,IPPROTO_UDP);
 
        if (s == INVALID_SOCKET) goto err;
 #if defined SOL_SOCKET && defined SO_REUSEADDR
@@ -301,8 +362,7 @@ static int init_server_long(int *sock, int port, char *ip)
                goto err;
                }
        /* Make it 128 for linux */
-       if (listen(s,128) == -1) goto err;
-       i=0;
+       if (type==SOCK_STREAM && listen(s,128) == -1) goto err;
        *sock=s;
        ret=1;
 err:
@@ -313,14 +373,14 @@ err:
        return(ret);
        }
 
-static int init_server(int *sock, int port)
+static int init_server(int *sock, int port, int type)
        {
-       return(init_server_long(sock, port, NULL));
+       return(init_server_long(sock, port, NULL, type));
        }
 
 static int do_accept(int acc_sock, int *sock, char **host)
        {
-       int ret,i;
+       int ret;
        struct hostent *h1,*h2;
        static struct sockaddr_in from;
        int len;
@@ -342,7 +402,8 @@ redoit:
        ret=accept(acc_sock,(struct sockaddr *)&from,(void *)&len);
        if (ret == INVALID_SOCKET)
                {
-#ifdef OPENSSL_SYS_WINDOWS
+#if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK))
+               int i;
                i=WSAGetLastError();
                BIO_printf(bio_err,"accept error %d\n",i);
 #else
@@ -389,7 +450,7 @@ redoit:
                        perror("OPENSSL_malloc");
                        return(0);
                        }
-               strcpy(*host,h1->h_name);
+               BUF_strlcpy(*host,h1->h_name,strlen(h1->h_name)+1);
 
                h2=GetHostByName(*host);
                if (h2 == NULL)
@@ -397,7 +458,6 @@ redoit:
                        BIO_printf(bio_err,"gethostbyname failure\n");
                        return(0);
                        }
-               i=0;
                if (h2->h_addrtype != AF_INET)
                        {
                        BIO_printf(bio_err,"gethostbyname addr is not AF_INET\n");
@@ -553,3 +613,5 @@ static struct hostent *GetHostByName(char *name)
                return(ret);
                }
        }
+
+#endif