159191Skris/* apps/s_socket.c - socket-related functions used by s_client and s_server */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 855714Skris * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1555714Skris * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 2255714Skris * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4055714Skris * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 5255714Skris * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 5855714Skris 5955714Skris#include <stdio.h> 6055714Skris#include <stdlib.h> 6155714Skris#include <string.h> 6255714Skris#include <errno.h> 6355714Skris#include <signal.h> 6455714Skris 65205128Ssimon#ifdef FLAT_INC 66205128Ssimon#include "e_os2.h" 67205128Ssimon#else 68205128Ssimon#include "../e_os2.h" 69205128Ssimon#endif 70205128Ssimon 7155714Skris/* With IPv6, it looks like Digital has mixed up the proper order of 7255714Skris recursive header file inclusion, resulting in the compiler complaining 7355714Skris that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which 7455714Skris is needed to have fileno() declared correctly... So let's define u_int */ 75109998Smarkm#if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT) 7655714Skris#define __U_INT 7755714Skristypedef unsigned int u_int; 7855714Skris#endif 7955714Skris 8055714Skris#define USE_SOCKETS 8155714Skris#define NON_MAIN 8255714Skris#include "apps.h" 8355714Skris#undef USE_SOCKETS 8455714Skris#undef NON_MAIN 8555714Skris#include "s_apps.h" 8655714Skris#include <openssl/ssl.h> 8755714Skris 88160814Ssimon#ifdef FLAT_INC 89160814Ssimon#include "e_os.h" 90160814Ssimon#else 91160814Ssimon#include "../e_os.h" 92160814Ssimon#endif 93160814Ssimon 94160814Ssimon#ifndef OPENSSL_NO_SOCK 95160814Ssimon 96160814Ssimon#if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_BSDSOCK) 97160814Ssimon#include "netdb.h" 98160814Ssimon#endif 99160814Ssimon 10059191Skrisstatic struct hostent *GetHostByName(char *name); 101160814Ssimon#if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)) 102109998Smarkmstatic void ssl_sock_cleanup(void); 10355714Skris#endif 104109998Smarkmstatic int ssl_sock_init(void); 105160814Ssimonstatic int init_client_ip(int *sock,unsigned char ip[4], int port, int type); 106160814Ssimonstatic int init_server(int *sock, int port, int type); 107160814Ssimonstatic int init_server_long(int *sock, int port,char *ip, int type); 10859191Skrisstatic int do_accept(int acc_sock, int *sock, char **host); 10959191Skrisstatic int host_ip(char *str, unsigned char ip[4]); 11055714Skris 111109998Smarkm#ifdef OPENSSL_SYS_WIN16 11255714Skris#define SOCKET_PROTOCOL 0 /* more microsoft stupidity */ 11355714Skris#else 11455714Skris#define SOCKET_PROTOCOL IPPROTO_TCP 11555714Skris#endif 11655714Skris 117160814Ssimon#if defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) 118160814Ssimonstatic int wsa_init_done=0; 119160814Ssimon#endif 120160814Ssimon 121109998Smarkm#ifdef OPENSSL_SYS_WINDOWS 12255714Skrisstatic struct WSAData wsa_state; 12355714Skrisstatic int wsa_init_done=0; 12455714Skris 125109998Smarkm#ifdef OPENSSL_SYS_WIN16 12655714Skrisstatic HWND topWnd=0; 12755714Skrisstatic FARPROC lpTopWndProc=NULL; 12855714Skrisstatic FARPROC lpTopHookProc=NULL; 12955714Skrisextern HINSTANCE _hInstance; /* nice global CRT provides */ 13055714Skris 13155714Skrisstatic LONG FAR PASCAL topHookProc(HWND hwnd, UINT message, WPARAM wParam, 13255714Skris LPARAM lParam) 13355714Skris { 13455714Skris if (hwnd == topWnd) 13555714Skris { 13655714Skris switch(message) 13755714Skris { 13855714Skris case WM_DESTROY: 13955714Skris case WM_CLOSE: 14055714Skris SetWindowLong(topWnd,GWL_WNDPROC,(LONG)lpTopWndProc); 141109998Smarkm ssl_sock_cleanup(); 14255714Skris break; 14355714Skris } 14455714Skris } 14555714Skris return CallWindowProc(lpTopWndProc,hwnd,message,wParam,lParam); 14655714Skris } 14755714Skris 14855714Skrisstatic BOOL CALLBACK enumproc(HWND hwnd,LPARAM lParam) 14955714Skris { 15055714Skris topWnd=hwnd; 15155714Skris return(FALSE); 15255714Skris } 15355714Skris 154109998Smarkm#endif /* OPENSSL_SYS_WIN32 */ 155109998Smarkm#endif /* OPENSSL_SYS_WINDOWS */ 15655714Skris 157109998Smarkm#ifdef OPENSSL_SYS_WINDOWS 158109998Smarkmstatic void ssl_sock_cleanup(void) 15955714Skris { 16055714Skris if (wsa_init_done) 16155714Skris { 16255714Skris wsa_init_done=0; 163109998Smarkm#ifndef OPENSSL_SYS_WINCE 16455714Skris WSACancelBlockingCall(); 165109998Smarkm#endif 16655714Skris WSACleanup(); 16755714Skris } 16859191Skris } 169160814Ssimon#elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) 170160814Ssimonstatic void sock_cleanup(void) 171160814Ssimon { 172160814Ssimon if (wsa_init_done) 173160814Ssimon { 174160814Ssimon wsa_init_done=0; 175160814Ssimon WSACleanup(); 176160814Ssimon } 177160814Ssimon } 17855714Skris#endif 17955714Skris 180109998Smarkmstatic int ssl_sock_init(void) 18155714Skris { 182109998Smarkm#ifdef WATT32 183109998Smarkm extern int _watt_do_exit; 184109998Smarkm _watt_do_exit = 0; 185109998Smarkm if (sock_init()) 186109998Smarkm return (0); 187109998Smarkm#elif defined(OPENSSL_SYS_WINDOWS) 18855714Skris if (!wsa_init_done) 18955714Skris { 19055714Skris int err; 19155714Skris 19255714Skris#ifdef SIGINT 193109998Smarkm signal(SIGINT,(void (*)(int))ssl_sock_cleanup); 19455714Skris#endif 19555714Skris wsa_init_done=1; 19655714Skris memset(&wsa_state,0,sizeof(wsa_state)); 19755714Skris if (WSAStartup(0x0101,&wsa_state)!=0) 19855714Skris { 19955714Skris err=WSAGetLastError(); 20055714Skris BIO_printf(bio_err,"unable to start WINSOCK, error code=%d\n",err); 20155714Skris return(0); 20255714Skris } 20355714Skris 204109998Smarkm#ifdef OPENSSL_SYS_WIN16 20555714Skris EnumTaskWindows(GetCurrentTask(),enumproc,0L); 20655714Skris lpTopWndProc=(FARPROC)GetWindowLong(topWnd,GWL_WNDPROC); 20755714Skris lpTopHookProc=MakeProcInstance((FARPROC)topHookProc,_hInstance); 20855714Skris 20955714Skris SetWindowLong(topWnd,GWL_WNDPROC,(LONG)lpTopHookProc); 210109998Smarkm#endif /* OPENSSL_SYS_WIN16 */ 21155714Skris } 212160814Ssimon#elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) 213160814Ssimon WORD wVerReq; 214160814Ssimon WSADATA wsaData; 215160814Ssimon int err; 216160814Ssimon 217160814Ssimon if (!wsa_init_done) 218160814Ssimon { 219160814Ssimon 220160814Ssimon# ifdef SIGINT 221160814Ssimon signal(SIGINT,(void (*)(int))sock_cleanup); 222160814Ssimon# endif 223160814Ssimon 224160814Ssimon wsa_init_done=1; 225160814Ssimon wVerReq = MAKEWORD( 2, 0 ); 226160814Ssimon err = WSAStartup(wVerReq,&wsaData); 227160814Ssimon if (err != 0) 228160814Ssimon { 229160814Ssimon BIO_printf(bio_err,"unable to start WINSOCK2, error code=%d\n",err); 230160814Ssimon return(0); 231160814Ssimon } 232160814Ssimon } 233109998Smarkm#endif /* OPENSSL_SYS_WINDOWS */ 23455714Skris return(1); 23555714Skris } 23655714Skris 237160814Ssimonint init_client(int *sock, char *host, int port, int type) 23855714Skris { 23955714Skris unsigned char ip[4]; 24055714Skris 241238405Sjkim memset(ip, '\0', sizeof ip); 24255714Skris if (!host_ip(host,&(ip[0]))) 243238405Sjkim return 0; 244238405Sjkim return init_client_ip(sock,ip,port,type); 24555714Skris } 24655714Skris 247160814Ssimonstatic int init_client_ip(int *sock, unsigned char ip[4], int port, int type) 24855714Skris { 24955714Skris unsigned long addr; 25055714Skris struct sockaddr_in them; 25155714Skris int s,i; 25255714Skris 253109998Smarkm if (!ssl_sock_init()) return(0); 25455714Skris 25555714Skris memset((char *)&them,0,sizeof(them)); 25655714Skris them.sin_family=AF_INET; 25755714Skris them.sin_port=htons((unsigned short)port); 25855714Skris addr=(unsigned long) 25955714Skris ((unsigned long)ip[0]<<24L)| 26055714Skris ((unsigned long)ip[1]<<16L)| 26155714Skris ((unsigned long)ip[2]<< 8L)| 26255714Skris ((unsigned long)ip[3]); 26355714Skris them.sin_addr.s_addr=htonl(addr); 26455714Skris 265160814Ssimon if (type == SOCK_STREAM) 266160814Ssimon s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); 267160814Ssimon else /* ( type == SOCK_DGRAM) */ 268160814Ssimon s=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); 269160814Ssimon 27055714Skris if (s == INVALID_SOCKET) { perror("socket"); return(0); } 27155714Skris 272238405Sjkim#if defined(SO_KEEPALIVE) && !defined(OPENSSL_SYS_MPE) 273160814Ssimon if (type == SOCK_STREAM) 274160814Ssimon { 275160814Ssimon i=0; 276160814Ssimon i=setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i)); 277279264Sdelphij if (i < 0) { closesocket(s); perror("keepalive"); return(0); } 278160814Ssimon } 27968651Skris#endif 28055714Skris 28155714Skris if (connect(s,(struct sockaddr *)&them,sizeof(them)) == -1) 282238405Sjkim { closesocket(s); perror("connect"); return(0); } 28355714Skris *sock=s; 28455714Skris return(1); 28555714Skris } 28655714Skris 287160814Ssimonint do_server(int port, int type, int *ret, int (*cb)(char *hostname, int s, unsigned char *context), unsigned char *context) 28855714Skris { 28955714Skris int sock; 290160814Ssimon char *name = NULL; 291238405Sjkim int accept_socket = 0; 29255714Skris int i; 29355714Skris 294160814Ssimon if (!init_server(&accept_socket,port,type)) return(0); 29555714Skris 29655714Skris if (ret != NULL) 29755714Skris { 29855714Skris *ret=accept_socket; 29955714Skris /* return(1);*/ 30055714Skris } 301160814Ssimon for (;;) 302160814Ssimon { 303160814Ssimon if (type==SOCK_STREAM) 30455714Skris { 305160814Ssimon if (do_accept(accept_socket,&sock,&name) == 0) 306160814Ssimon { 307160814Ssimon SHUTDOWN(accept_socket); 308160814Ssimon return(0); 309160814Ssimon } 31055714Skris } 311160814Ssimon else 312160814Ssimon sock = accept_socket; 31355714Skris i=(*cb)(name,sock, context); 31468651Skris if (name != NULL) OPENSSL_free(name); 315160814Ssimon if (type==SOCK_STREAM) 316160814Ssimon SHUTDOWN2(sock); 31755714Skris if (i < 0) 31855714Skris { 31955714Skris SHUTDOWN2(accept_socket); 32055714Skris return(i); 32155714Skris } 32255714Skris } 32355714Skris } 32455714Skris 325160814Ssimonstatic int init_server_long(int *sock, int port, char *ip, int type) 32655714Skris { 32755714Skris int ret=0; 32855714Skris struct sockaddr_in server; 329215697Ssimon int s= -1; 33055714Skris 331109998Smarkm if (!ssl_sock_init()) return(0); 33255714Skris 33355714Skris memset((char *)&server,0,sizeof(server)); 33455714Skris server.sin_family=AF_INET; 33555714Skris server.sin_port=htons((unsigned short)port); 33655714Skris if (ip == NULL) 33755714Skris server.sin_addr.s_addr=INADDR_ANY; 33855714Skris else 33955714Skris/* Added for T3E, address-of fails on bit field (beckman@acl.lanl.gov) */ 34055714Skris#ifndef BIT_FIELD_LIMITS 34155714Skris memcpy(&server.sin_addr.s_addr,ip,4); 34255714Skris#else 34355714Skris memcpy(&server.sin_addr,ip,4); 34455714Skris#endif 345160814Ssimon 346160814Ssimon if (type == SOCK_STREAM) 347160814Ssimon s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); 348160814Ssimon else /* type == SOCK_DGRAM */ 349160814Ssimon s=socket(AF_INET, SOCK_DGRAM,IPPROTO_UDP); 35055714Skris 35155714Skris if (s == INVALID_SOCKET) goto err; 35255714Skris#if defined SOL_SOCKET && defined SO_REUSEADDR 35355714Skris { 35455714Skris int j = 1; 35555714Skris setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 35655714Skris (void *) &j, sizeof j); 35755714Skris } 35855714Skris#endif 35955714Skris if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1) 36055714Skris { 361109998Smarkm#ifndef OPENSSL_SYS_WINDOWS 36255714Skris perror("bind"); 36355714Skris#endif 36455714Skris goto err; 36555714Skris } 36655714Skris /* Make it 128 for linux */ 367160814Ssimon if (type==SOCK_STREAM && listen(s,128) == -1) goto err; 36855714Skris *sock=s; 36955714Skris ret=1; 37055714Skriserr: 37155714Skris if ((ret == 0) && (s != -1)) 37255714Skris { 37355714Skris SHUTDOWN(s); 37455714Skris } 37555714Skris return(ret); 37655714Skris } 37755714Skris 378160814Ssimonstatic int init_server(int *sock, int port, int type) 37955714Skris { 380160814Ssimon return(init_server_long(sock, port, NULL, type)); 38155714Skris } 38255714Skris 38359191Skrisstatic int do_accept(int acc_sock, int *sock, char **host) 38455714Skris { 385215697Ssimon int ret; 38655714Skris struct hostent *h1,*h2; 38755714Skris static struct sockaddr_in from; 38855714Skris int len; 38955714Skris/* struct linger ling; */ 39055714Skris 391109998Smarkm if (!ssl_sock_init()) return(0); 39255714Skris 393109998Smarkm#ifndef OPENSSL_SYS_WINDOWS 39455714Skrisredoit: 39555714Skris#endif 39655714Skris 39755714Skris memset((char *)&from,0,sizeof(from)); 39855714Skris len=sizeof(from); 39955714Skris /* Note: under VMS with SOCKETSHR the fourth parameter is currently 40055714Skris * of type (int *) whereas under other systems it is (void *) if 40155714Skris * you don't have a cast it will choke the compiler: if you do 40255714Skris * have a cast then you can either go for (int *) or (void *). 40355714Skris */ 40455714Skris ret=accept(acc_sock,(struct sockaddr *)&from,(void *)&len); 40555714Skris if (ret == INVALID_SOCKET) 40655714Skris { 407160814Ssimon#if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)) 408215697Ssimon int i; 40955714Skris i=WSAGetLastError(); 41055714Skris BIO_printf(bio_err,"accept error %d\n",i); 41155714Skris#else 41255714Skris if (errno == EINTR) 41355714Skris { 41455714Skris /*check_timeout(); */ 41555714Skris goto redoit; 41655714Skris } 41755714Skris fprintf(stderr,"errno=%d ",errno); 41855714Skris perror("accept"); 41955714Skris#endif 42055714Skris return(0); 42155714Skris } 42255714Skris 42355714Skris/* 42455714Skris ling.l_onoff=1; 42555714Skris ling.l_linger=0; 42655714Skris i=setsockopt(ret,SOL_SOCKET,SO_LINGER,(char *)&ling,sizeof(ling)); 42755714Skris if (i < 0) { perror("linger"); return(0); } 42855714Skris i=0; 42955714Skris i=setsockopt(ret,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i)); 43055714Skris if (i < 0) { perror("keepalive"); return(0); } 43155714Skris*/ 43255714Skris 43355714Skris if (host == NULL) goto end; 43455714Skris#ifndef BIT_FIELD_LIMITS 43555714Skris /* I should use WSAAsyncGetHostByName() under windows */ 43655714Skris h1=gethostbyaddr((char *)&from.sin_addr.s_addr, 43755714Skris sizeof(from.sin_addr.s_addr),AF_INET); 43855714Skris#else 43955714Skris h1=gethostbyaddr((char *)&from.sin_addr, 44055714Skris sizeof(struct in_addr),AF_INET); 44155714Skris#endif 44255714Skris if (h1 == NULL) 44355714Skris { 44455714Skris BIO_printf(bio_err,"bad gethostbyaddr\n"); 44555714Skris *host=NULL; 44655714Skris /* return(0); */ 44755714Skris } 44855714Skris else 44955714Skris { 45068651Skris if ((*host=(char *)OPENSSL_malloc(strlen(h1->h_name)+1)) == NULL) 45155714Skris { 45268651Skris perror("OPENSSL_malloc"); 453279264Sdelphij closesocket(ret); 45455714Skris return(0); 45555714Skris } 456127128Snectar BUF_strlcpy(*host,h1->h_name,strlen(h1->h_name)+1); 45755714Skris 45855714Skris h2=GetHostByName(*host); 45955714Skris if (h2 == NULL) 46055714Skris { 46155714Skris BIO_printf(bio_err,"gethostbyname failure\n"); 462279264Sdelphij closesocket(ret); 46355714Skris return(0); 46455714Skris } 46555714Skris if (h2->h_addrtype != AF_INET) 46655714Skris { 46755714Skris BIO_printf(bio_err,"gethostbyname addr is not AF_INET\n"); 468279264Sdelphij closesocket(ret); 46955714Skris return(0); 47055714Skris } 47155714Skris } 47255714Skrisend: 47355714Skris *sock=ret; 47455714Skris return(1); 47555714Skris } 47655714Skris 47755714Skrisint extract_host_port(char *str, char **host_ptr, unsigned char *ip, 47855714Skris short *port_ptr) 47955714Skris { 48055714Skris char *h,*p; 48155714Skris 48255714Skris h=str; 48355714Skris p=strchr(str,':'); 48455714Skris if (p == NULL) 48555714Skris { 48655714Skris BIO_printf(bio_err,"no port defined\n"); 48755714Skris return(0); 48855714Skris } 48955714Skris *(p++)='\0'; 49055714Skris 49155714Skris if ((ip != NULL) && !host_ip(str,ip)) 49255714Skris goto err; 49355714Skris if (host_ptr != NULL) *host_ptr=h; 49455714Skris 49555714Skris if (!extract_port(p,port_ptr)) 49655714Skris goto err; 49755714Skris return(1); 49855714Skriserr: 49955714Skris return(0); 50055714Skris } 50155714Skris 50259191Skrisstatic int host_ip(char *str, unsigned char ip[4]) 50355714Skris { 50455714Skris unsigned int in[4]; 50555714Skris int i; 50655714Skris 50755714Skris if (sscanf(str,"%u.%u.%u.%u",&(in[0]),&(in[1]),&(in[2]),&(in[3])) == 4) 50855714Skris { 50955714Skris for (i=0; i<4; i++) 51055714Skris if (in[i] > 255) 51155714Skris { 51255714Skris BIO_printf(bio_err,"invalid IP address\n"); 51355714Skris goto err; 51455714Skris } 51555714Skris ip[0]=in[0]; 51655714Skris ip[1]=in[1]; 51755714Skris ip[2]=in[2]; 51855714Skris ip[3]=in[3]; 51955714Skris } 52055714Skris else 52155714Skris { /* do a gethostbyname */ 52255714Skris struct hostent *he; 52355714Skris 524109998Smarkm if (!ssl_sock_init()) return(0); 52555714Skris 52655714Skris he=GetHostByName(str); 52755714Skris if (he == NULL) 52855714Skris { 52955714Skris BIO_printf(bio_err,"gethostbyname failure\n"); 53055714Skris goto err; 53155714Skris } 53255714Skris /* cast to short because of win16 winsock definition */ 53355714Skris if ((short)he->h_addrtype != AF_INET) 53455714Skris { 53555714Skris BIO_printf(bio_err,"gethostbyname addr is not AF_INET\n"); 53655714Skris return(0); 53755714Skris } 53855714Skris ip[0]=he->h_addr_list[0][0]; 53955714Skris ip[1]=he->h_addr_list[0][1]; 54055714Skris ip[2]=he->h_addr_list[0][2]; 54155714Skris ip[3]=he->h_addr_list[0][3]; 54255714Skris } 54355714Skris return(1); 54455714Skriserr: 54555714Skris return(0); 54655714Skris } 54755714Skris 54855714Skrisint extract_port(char *str, short *port_ptr) 54955714Skris { 55055714Skris int i; 55155714Skris struct servent *s; 55255714Skris 55355714Skris i=atoi(str); 55455714Skris if (i != 0) 55555714Skris *port_ptr=(unsigned short)i; 55655714Skris else 55755714Skris { 55855714Skris s=getservbyname(str,"tcp"); 55955714Skris if (s == NULL) 56055714Skris { 56155714Skris BIO_printf(bio_err,"getservbyname failure for %s\n",str); 56255714Skris return(0); 56355714Skris } 56455714Skris *port_ptr=ntohs((unsigned short)s->s_port); 56555714Skris } 56655714Skris return(1); 56755714Skris } 56855714Skris 56955714Skris#define GHBN_NUM 4 57055714Skrisstatic struct ghbn_cache_st 57155714Skris { 57255714Skris char name[128]; 57355714Skris struct hostent ent; 57455714Skris unsigned long order; 57555714Skris } ghbn_cache[GHBN_NUM]; 57655714Skris 57755714Skrisstatic unsigned long ghbn_hits=0L; 57855714Skrisstatic unsigned long ghbn_miss=0L; 57955714Skris 58055714Skrisstatic struct hostent *GetHostByName(char *name) 58155714Skris { 58255714Skris struct hostent *ret; 58355714Skris int i,lowi=0; 58455714Skris unsigned long low= (unsigned long)-1; 58555714Skris 58655714Skris for (i=0; i<GHBN_NUM; i++) 58755714Skris { 58855714Skris if (low > ghbn_cache[i].order) 58955714Skris { 59055714Skris low=ghbn_cache[i].order; 59155714Skris lowi=i; 59255714Skris } 59355714Skris if (ghbn_cache[i].order > 0) 59455714Skris { 59555714Skris if (strncmp(name,ghbn_cache[i].name,128) == 0) 59655714Skris break; 59755714Skris } 59855714Skris } 59955714Skris if (i == GHBN_NUM) /* no hit*/ 60055714Skris { 60155714Skris ghbn_miss++; 60255714Skris ret=gethostbyname(name); 60355714Skris if (ret == NULL) return(NULL); 60455714Skris /* else add to cache */ 605109998Smarkm if(strlen(name) < sizeof ghbn_cache[0].name) 606109998Smarkm { 607109998Smarkm strcpy(ghbn_cache[lowi].name,name); 608109998Smarkm memcpy((char *)&(ghbn_cache[lowi].ent),ret,sizeof(struct hostent)); 609109998Smarkm ghbn_cache[lowi].order=ghbn_miss+ghbn_hits; 610109998Smarkm } 61155714Skris return(ret); 61255714Skris } 61355714Skris else 61455714Skris { 61555714Skris ghbn_hits++; 61655714Skris ret= &(ghbn_cache[i].ent); 61755714Skris ghbn_cache[i].order=ghbn_miss+ghbn_hits; 61855714Skris return(ret); 61955714Skris } 62055714Skris } 621160814Ssimon 622160814Ssimon#endif 623