s_socket.c revision 238405
167754Smsmith/* apps/s_socket.c - socket-related functions used by s_client and s_server */ 267754Smsmith/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3167802Sjkim * All rights reserved. 467754Smsmith * 567754Smsmith * This package is an SSL implementation written 667754Smsmith * by Eric Young (eay@cryptsoft.com). 767754Smsmith * The implementation was written so as to conform with Netscapes SSL. 867754Smsmith * 967754Smsmith * This library is free for commercial and non-commercial use as long as 1067754Smsmith * the following conditions are aheared to. The following conditions 11193267Sjkim * apply to all code found in this distribution, be it the RC4, RSA, 1270243Smsmith * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1367754Smsmith * included with this distribution is covered by the same copyright terms 1467754Smsmith * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1567754Smsmith * 1667754Smsmith * Copyright remains Eric Young's, and as such any Copyright notices in 1767754Smsmith * the code are not to be removed. 1867754Smsmith * If this package is used in a product, Eric Young should be given attribution 1967754Smsmith * as the author of the parts of the library used. 2067754Smsmith * This can be in the form of a textual message at program startup or 2167754Smsmith * in documentation (online or textual) provided with the package. 2267754Smsmith * 2367754Smsmith * Redistribution and use in source and binary forms, with or without 2467754Smsmith * modification, are permitted provided that the following conditions 2567754Smsmith * are met: 2667754Smsmith * 1. Redistributions of source code must retain the copyright 2767754Smsmith * notice, this list of conditions and the following disclaimer. 2867754Smsmith * 2. Redistributions in binary form must reproduce the above copyright 2967754Smsmith * notice, this list of conditions and the following disclaimer in the 3067754Smsmith * documentation and/or other materials provided with the distribution. 3167754Smsmith * 3. All advertising materials mentioning features or use of this software 3267754Smsmith * must display the following acknowledgement: 3367754Smsmith * "This product includes cryptographic software written by 3467754Smsmith * Eric Young (eay@cryptsoft.com)" 3567754Smsmith * The word 'cryptographic' can be left out if the rouines from the library 3667754Smsmith * being used are not cryptographic related :-). 3767754Smsmith * 4. If you include any Windows specific code (or a derivative thereof) from 3867754Smsmith * the apps directory (application code) you must include an acknowledgement: 3967754Smsmith * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4067754Smsmith * 4167754Smsmith * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4267754Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4367754Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4467754Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4567754Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4667754Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4767754Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4867754Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4967754Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5067754Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5167754Smsmith * SUCH DAMAGE. 5267754Smsmith * 5367754Smsmith * The licence and distribution terms for any publically available version or 5467754Smsmith * derivative of this code cannot be changed. i.e. this code cannot simply be 5567754Smsmith * copied and put under another distribution licence 5667754Smsmith * [including the GNU Public Licence.] 5767754Smsmith */ 5867754Smsmith 5967754Smsmith#include <stdio.h> 6067754Smsmith#include <stdlib.h> 6167754Smsmith#include <string.h> 6267754Smsmith#include <errno.h> 6367754Smsmith#include <signal.h> 6467754Smsmith 6567754Smsmith#ifdef FLAT_INC 6667754Smsmith#include "e_os2.h" 6767754Smsmith#else 6867754Smsmith#include "../e_os2.h" 6967754Smsmith#endif 7067754Smsmith 7167754Smsmith/* With IPv6, it looks like Digital has mixed up the proper order of 7267754Smsmith recursive header file inclusion, resulting in the compiler complaining 7367754Smsmith that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which 7467754Smsmith is needed to have fileno() declared correctly... So let's define u_int */ 7567754Smsmith#if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT) 7667754Smsmith#define __U_INT 7767754Smsmithtypedef unsigned int u_int; 7867754Smsmith#endif 7967754Smsmith 8067754Smsmith#define USE_SOCKETS 8167754Smsmith#define NON_MAIN 8267754Smsmith#include "apps.h" 8367754Smsmith#undef USE_SOCKETS 8467754Smsmith#undef NON_MAIN 8567754Smsmith#include "s_apps.h" 8667754Smsmith#include <openssl/ssl.h> 8767754Smsmith 8867754Smsmith#ifdef FLAT_INC 8967754Smsmith#include "e_os.h" 9067754Smsmith#else 9167754Smsmith#include "../e_os.h" 9267754Smsmith#endif 9367754Smsmith 9467754Smsmith#ifndef OPENSSL_NO_SOCK 9567754Smsmith 9667754Smsmith#if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_BSDSOCK) 9767754Smsmith#include "netdb.h" 9867754Smsmith#endif 9967754Smsmith 10067754Smsmithstatic struct hostent *GetHostByName(char *name); 10167754Smsmith#if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)) 10267754Smsmithstatic void ssl_sock_cleanup(void); 10367754Smsmith#endif 10467754Smsmithstatic int ssl_sock_init(void); 10567754Smsmithstatic int init_client_ip(int *sock,unsigned char ip[4], int port, int type); 10667754Smsmithstatic int init_server(int *sock, int port, int type); 10767754Smsmithstatic int init_server_long(int *sock, int port,char *ip, int type); 10867754Smsmithstatic int do_accept(int acc_sock, int *sock, char **host); 10967754Smsmithstatic int host_ip(char *str, unsigned char ip[4]); 11067754Smsmith 11167754Smsmith#ifdef OPENSSL_SYS_WIN16 11267754Smsmith#define SOCKET_PROTOCOL 0 /* more microsoft stupidity */ 11367754Smsmith#else 11467754Smsmith#define SOCKET_PROTOCOL IPPROTO_TCP 11567754Smsmith#endif 11667754Smsmith 11767754Smsmith#if defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) 118193341Sjkimstatic int wsa_init_done=0; 119193341Sjkim#endif 120193341Sjkim 12167754Smsmith#ifdef OPENSSL_SYS_WINDOWS 12277424Smsmithstatic struct WSAData wsa_state; 12391116Smsmithstatic int wsa_init_done=0; 12467754Smsmith 125151937Sjkim#ifdef OPENSSL_SYS_WIN16 12667754Smsmithstatic HWND topWnd=0; 127197104Sjkimstatic FARPROC lpTopWndProc=NULL; 128197104Sjkimstatic FARPROC lpTopHookProc=NULL; 129197104Sjkimextern HINSTANCE _hInstance; /* nice global CRT provides */ 130197104Sjkim 131197104Sjkimstatic LONG FAR PASCAL topHookProc(HWND hwnd, UINT message, WPARAM wParam, 132197104Sjkim LPARAM lParam) 133197104Sjkim { 134197104Sjkim if (hwnd == topWnd) 135197104Sjkim { 136197104Sjkim switch(message) 137167802Sjkim { 138167802Sjkim case WM_DESTROY: 139167802Sjkim case WM_CLOSE: 140193267Sjkim SetWindowLong(topWnd,GWL_WNDPROC,(LONG)lpTopWndProc); 141151937Sjkim ssl_sock_cleanup(); 142151937Sjkim break; 14367754Smsmith } 14467754Smsmith } 145193267Sjkim return CallWindowProc(lpTopWndProc,hwnd,message,wParam,lParam); 146193267Sjkim } 147193267Sjkim 148193267Sjkimstatic BOOL CALLBACK enumproc(HWND hwnd,LPARAM lParam) 149193267Sjkim { 150193267Sjkim topWnd=hwnd; 151193267Sjkim return(FALSE); 152193267Sjkim } 153193267Sjkim 154193267Sjkim#endif /* OPENSSL_SYS_WIN32 */ 155193267Sjkim#endif /* OPENSSL_SYS_WINDOWS */ 156193267Sjkim 157193267Sjkim#ifdef OPENSSL_SYS_WINDOWS 158193267Sjkimstatic void ssl_sock_cleanup(void) 159193267Sjkim { 160193267Sjkim if (wsa_init_done) 161193267Sjkim { 162193267Sjkim wsa_init_done=0; 163193267Sjkim#ifndef OPENSSL_SYS_WINCE 164193267Sjkim WSACancelBlockingCall(); 165193267Sjkim#endif 166193267Sjkim WSACleanup(); 167193267Sjkim } 168193267Sjkim } 169193267Sjkim#elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) 170193267Sjkimstatic void sock_cleanup(void) 171167802Sjkim { 17267754Smsmith if (wsa_init_done) 173167802Sjkim { 17467754Smsmith wsa_init_done=0; 175167802Sjkim WSACleanup(); 17667754Smsmith } 177167802Sjkim } 178167802Sjkim#endif 179151937Sjkim 18067754Smsmithstatic int ssl_sock_init(void) 18167754Smsmith { 182167802Sjkim#ifdef WATT32 183167802Sjkim extern int _watt_do_exit; 184167802Sjkim _watt_do_exit = 0; 18567754Smsmith if (sock_init()) 18667754Smsmith return (0); 187167802Sjkim#elif defined(OPENSSL_SYS_WINDOWS) 188167802Sjkim if (!wsa_init_done) 189167802Sjkim { 190167802Sjkim int err; 19183174Smsmith 192167802Sjkim#ifdef SIGINT 193167802Sjkim signal(SIGINT,(void (*)(int))ssl_sock_cleanup); 19467754Smsmith#endif 19582367Smsmith wsa_init_done=1; 196167802Sjkim memset(&wsa_state,0,sizeof(wsa_state)); 197167802Sjkim if (WSAStartup(0x0101,&wsa_state)!=0) 198197104Sjkim { 199197104Sjkim err=WSAGetLastError(); 200197104Sjkim BIO_printf(bio_err,"unable to start WINSOCK, error code=%d\n",err); 201197104Sjkim return(0); 202197104Sjkim } 203197104Sjkim 204197104Sjkim#ifdef OPENSSL_SYS_WIN16 205197104Sjkim EnumTaskWindows(GetCurrentTask(),enumproc,0L); 206197104Sjkim lpTopWndProc=(FARPROC)GetWindowLong(topWnd,GWL_WNDPROC); 207197104Sjkim lpTopHookProc=MakeProcInstance((FARPROC)topHookProc,_hInstance); 208197104Sjkim 209197104Sjkim SetWindowLong(topWnd,GWL_WNDPROC,(LONG)lpTopHookProc); 210197104Sjkim#endif /* OPENSSL_SYS_WIN16 */ 211197104Sjkim } 212197104Sjkim#elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) 213197104Sjkim WORD wVerReq; 214197104Sjkim WSADATA wsaData; 215197104Sjkim int err; 216197104Sjkim 217197104Sjkim if (!wsa_init_done) 218197104Sjkim { 219197104Sjkim 220197104Sjkim# ifdef SIGINT 221197104Sjkim signal(SIGINT,(void (*)(int))sock_cleanup); 222197104Sjkim# endif 223197104Sjkim 224197104Sjkim wsa_init_done=1; 225197104Sjkim wVerReq = MAKEWORD( 2, 0 ); 226197104Sjkim err = WSAStartup(wVerReq,&wsaData); 227197104Sjkim if (err != 0) 228197104Sjkim { 229197104Sjkim BIO_printf(bio_err,"unable to start WINSOCK2, error code=%d\n",err); 230197104Sjkim return(0); 231197104Sjkim } 232197104Sjkim } 233197104Sjkim#endif /* OPENSSL_SYS_WINDOWS */ 234197104Sjkim return(1); 235197104Sjkim } 236197104Sjkim 237197104Sjkimint init_client(int *sock, char *host, int port, int type) 238197104Sjkim { 239197104Sjkim unsigned char ip[4]; 240197104Sjkim 241197104Sjkim memset(ip, '\0', sizeof ip); 242197104Sjkim if (!host_ip(host,&(ip[0]))) 243197104Sjkim return 0; 244197104Sjkim return init_client_ip(sock,ip,port,type); 245197104Sjkim } 246197104Sjkim 247197104Sjkimstatic int init_client_ip(int *sock, unsigned char ip[4], int port, int type) 248197104Sjkim { 249197104Sjkim unsigned long addr; 250197104Sjkim struct sockaddr_in them; 251197104Sjkim int s,i; 252197104Sjkim 253197104Sjkim if (!ssl_sock_init()) return(0); 254197104Sjkim 255197104Sjkim memset((char *)&them,0,sizeof(them)); 256197104Sjkim them.sin_family=AF_INET; 257197104Sjkim them.sin_port=htons((unsigned short)port); 258197104Sjkim addr=(unsigned long) 259167802Sjkim ((unsigned long)ip[0]<<24L)| 260167802Sjkim ((unsigned long)ip[1]<<16L)| 261167802Sjkim ((unsigned long)ip[2]<< 8L)| 262167802Sjkim ((unsigned long)ip[3]); 263167802Sjkim them.sin_addr.s_addr=htonl(addr); 264167802Sjkim 265167802Sjkim if (type == SOCK_STREAM) 266167802Sjkim s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); 267167802Sjkim else /* ( type == SOCK_DGRAM) */ 268167802Sjkim s=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); 269151937Sjkim 270167802Sjkim if (s == INVALID_SOCKET) { perror("socket"); return(0); } 271167802Sjkim 272167802Sjkim#if defined(SO_KEEPALIVE) && !defined(OPENSSL_SYS_MPE) 273167802Sjkim if (type == SOCK_STREAM) 274167802Sjkim { 275197104Sjkim i=0; 276151937Sjkim i=setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i)); 277197104Sjkim if (i < 0) { perror("keepalive"); return(0); } 278193267Sjkim } 279193267Sjkim#endif 280193267Sjkim 281193267Sjkim if (connect(s,(struct sockaddr *)&them,sizeof(them)) == -1) 282167802Sjkim { closesocket(s); perror("connect"); return(0); } 283167802Sjkim *sock=s; 284193267Sjkim return(1); 285151937Sjkim } 286193267Sjkim 287193267Sjkimint do_server(int port, int type, int *ret, int (*cb)(char *hostname, int s, unsigned char *context), unsigned char *context) 288193267Sjkim { 289167802Sjkim int sock; 290167802Sjkim char *name = NULL; 29167754Smsmith int accept_socket = 0; 292167802Sjkim int i; 29367754Smsmith 294197104Sjkim if (!init_server(&accept_socket,port,type)) return(0); 295197104Sjkim 296197104Sjkim if (ret != NULL) 297197104Sjkim { 298193267Sjkim *ret=accept_socket; 299167802Sjkim /* return(1);*/ 300167802Sjkim } 301167802Sjkim for (;;) 302167802Sjkim { 303197104Sjkim if (type==SOCK_STREAM) 304167802Sjkim { 305167802Sjkim if (do_accept(accept_socket,&sock,&name) == 0) 306167802Sjkim { 307167802Sjkim SHUTDOWN(accept_socket); 308151937Sjkim return(0); 309197104Sjkim } 310197104Sjkim } 311167802Sjkim else 312193267Sjkim sock = accept_socket; 313197104Sjkim i=(*cb)(name,sock, context); 314197104Sjkim if (name != NULL) OPENSSL_free(name); 315197104Sjkim if (type==SOCK_STREAM) 316197104Sjkim SHUTDOWN2(sock); 31767754Smsmith if (i < 0) 31867754Smsmith { 31967754Smsmith SHUTDOWN2(accept_socket); 32067754Smsmith return(i); 32167754Smsmith } 32267754Smsmith } 323167802Sjkim } 32467754Smsmith 325167802Sjkimstatic int init_server_long(int *sock, int port, char *ip, int type) 326167802Sjkim { 32767754Smsmith int ret=0; 32867754Smsmith struct sockaddr_in server; 32967754Smsmith int s= -1; 330167802Sjkim 331167802Sjkim if (!ssl_sock_init()) return(0); 33267754Smsmith 33367754Smsmith memset((char *)&server,0,sizeof(server)); 33467754Smsmith server.sin_family=AF_INET; 33567754Smsmith server.sin_port=htons((unsigned short)port); 336167802Sjkim if (ip == NULL) 337167802Sjkim server.sin_addr.s_addr=INADDR_ANY; 338167802Sjkim else 33967754Smsmith/* Added for T3E, address-of fails on bit field (beckman@acl.lanl.gov) */ 340167802Sjkim#ifndef BIT_FIELD_LIMITS 34167754Smsmith memcpy(&server.sin_addr.s_addr,ip,4); 34267754Smsmith#else 343167802Sjkim memcpy(&server.sin_addr,ip,4); 34477424Smsmith#endif 345167802Sjkim 34677424Smsmith if (type == SOCK_STREAM) 347167802Sjkim s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); 34867754Smsmith else /* type == SOCK_DGRAM */ 349167802Sjkim s=socket(AF_INET, SOCK_DGRAM,IPPROTO_UDP); 35067754Smsmith 351167802Sjkim if (s == INVALID_SOCKET) goto err; 352193267Sjkim#if defined SOL_SOCKET && defined SO_REUSEADDR 353193267Sjkim { 354193267Sjkim int j = 1; 355151937Sjkim setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 356167802Sjkim (void *) &j, sizeof j); 357167802Sjkim } 358167802Sjkim#endif 35967754Smsmith if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1) 36067754Smsmith { 361167802Sjkim#ifndef OPENSSL_SYS_WINDOWS 362167802Sjkim perror("bind"); 36367754Smsmith#endif 36467754Smsmith goto err; 365167802Sjkim } 366167802Sjkim /* Make it 128 for linux */ 367167802Sjkim if (type==SOCK_STREAM && listen(s,128) == -1) goto err; 368167802Sjkim *sock=s; 369167802Sjkim ret=1; 370167802Sjkimerr: 371167802Sjkim if ((ret == 0) && (s != -1)) 372167802Sjkim { 373167802Sjkim SHUTDOWN(s); 374167802Sjkim } 375167802Sjkim return(ret); 376167802Sjkim } 377151937Sjkim 378167802Sjkimstatic int init_server(int *sock, int port, int type) 379167802Sjkim { 380167802Sjkim return(init_server_long(sock, port, NULL, type)); 381193267Sjkim } 382167802Sjkim 383167802Sjkimstatic int do_accept(int acc_sock, int *sock, char **host) 384167802Sjkim { 38567754Smsmith int ret; 38667754Smsmith struct hostent *h1,*h2; 387167802Sjkim static struct sockaddr_in from; 38867754Smsmith int len; 389167802Sjkim/* struct linger ling; */ 39067754Smsmith 39167754Smsmith if (!ssl_sock_init()) return(0); 392167802Sjkim 39367754Smsmith#ifndef OPENSSL_SYS_WINDOWS 39467754Smsmithredoit: 39567754Smsmith#endif 39667754Smsmith 39767754Smsmith memset((char *)&from,0,sizeof(from)); 398167802Sjkim len=sizeof(from); 39967754Smsmith /* Note: under VMS with SOCKETSHR the fourth parameter is currently 400167802Sjkim * of type (int *) whereas under other systems it is (void *) if 401167802Sjkim * you don't have a cast it will choke the compiler: if you do 402167802Sjkim * have a cast then you can either go for (int *) or (void *). 403167802Sjkim */ 40467754Smsmith ret=accept(acc_sock,(struct sockaddr *)&from,(void *)&len); 405167802Sjkim if (ret == INVALID_SOCKET) 40667754Smsmith { 407193267Sjkim#if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)) 408193267Sjkim int i; 409193267Sjkim i=WSAGetLastError(); 410193267Sjkim BIO_printf(bio_err,"accept error %d\n",i); 41167754Smsmith#else 41267754Smsmith if (errno == EINTR) 41367754Smsmith { 414167802Sjkim /*check_timeout(); */ 415167802Sjkim goto redoit; 416167802Sjkim } 417167802Sjkim fprintf(stderr,"errno=%d ",errno); 418193267Sjkim perror("accept"); 41967754Smsmith#endif 420193267Sjkim return(0); 421193267Sjkim } 422193267Sjkim 423193267Sjkim/* 424193267Sjkim ling.l_onoff=1; 42567754Smsmith ling.l_linger=0; 42667754Smsmith i=setsockopt(ret,SOL_SOCKET,SO_LINGER,(char *)&ling,sizeof(ling)); 427167802Sjkim if (i < 0) { perror("linger"); return(0); } 428167802Sjkim i=0; 429167802Sjkim i=setsockopt(ret,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i)); 430167802Sjkim if (i < 0) { perror("keepalive"); return(0); } 431167802Sjkim*/ 432167802Sjkim 43367754Smsmith if (host == NULL) goto end; 434167802Sjkim#ifndef BIT_FIELD_LIMITS 43567754Smsmith /* I should use WSAAsyncGetHostByName() under windows */ 436193267Sjkim h1=gethostbyaddr((char *)&from.sin_addr.s_addr, 437193267Sjkim sizeof(from.sin_addr.s_addr),AF_INET); 438167802Sjkim#else 439167802Sjkim h1=gethostbyaddr((char *)&from.sin_addr, 440167802Sjkim sizeof(struct in_addr),AF_INET); 44167754Smsmith#endif 442193453Sjkim if (h1 == NULL) 443193453Sjkim { 444193453Sjkim BIO_printf(bio_err,"bad gethostbyaddr\n"); 445193453Sjkim *host=NULL; 446193453Sjkim /* return(0); */ 447193453Sjkim } 448193453Sjkim else 449193453Sjkim { 450193453Sjkim if ((*host=(char *)OPENSSL_malloc(strlen(h1->h_name)+1)) == NULL) 451193453Sjkim { 452193453Sjkim perror("OPENSSL_malloc"); 453193453Sjkim return(0); 454193453Sjkim } 455193453Sjkim BUF_strlcpy(*host,h1->h_name,strlen(h1->h_name)+1); 456193453Sjkim 457193267Sjkim h2=GetHostByName(*host); 45867754Smsmith if (h2 == NULL) 459167802Sjkim { 460193267Sjkim BIO_printf(bio_err,"gethostbyname failure\n"); 461167802Sjkim return(0); 462193267Sjkim } 463193267Sjkim if (h2->h_addrtype != AF_INET) 464193267Sjkim { 465167802Sjkim BIO_printf(bio_err,"gethostbyname addr is not AF_INET\n"); 466167802Sjkim return(0); 46767754Smsmith } 468193267Sjkim } 469193267Sjkimend: 470193267Sjkim *sock=ret; 471193267Sjkim return(1); 472193267Sjkim } 473193267Sjkim 474193267Sjkimint extract_host_port(char *str, char **host_ptr, unsigned char *ip, 475193267Sjkim short *port_ptr) 476193267Sjkim { 477193267Sjkim char *h,*p; 478193267Sjkim 479193267Sjkim h=str; 480193267Sjkim p=strchr(str,':'); 481193267Sjkim if (p == NULL) 482193267Sjkim { 483193267Sjkim BIO_printf(bio_err,"no port defined\n"); 484193267Sjkim return(0); 485193267Sjkim } 486193267Sjkim *(p++)='\0'; 487193267Sjkim 488193267Sjkim if ((ip != NULL) && !host_ip(str,ip)) 489193267Sjkim goto err; 490193267Sjkim if (host_ptr != NULL) *host_ptr=h; 491193267Sjkim 492193267Sjkim if (!extract_port(p,port_ptr)) 493193267Sjkim goto err; 494167802Sjkim return(1); 495167802Sjkimerr: 496167802Sjkim return(0); 497193267Sjkim } 498167802Sjkim 499167802Sjkimstatic int host_ip(char *str, unsigned char ip[4]) 500167802Sjkim { 501167802Sjkim unsigned int in[4]; 502193267Sjkim int i; 503167802Sjkim 504193267Sjkim if (sscanf(str,"%u.%u.%u.%u",&(in[0]),&(in[1]),&(in[2]),&(in[3])) == 4) 505167802Sjkim { 506167802Sjkim for (i=0; i<4; i++) 50767754Smsmith if (in[i] > 255) 508167802Sjkim { 50967754Smsmith BIO_printf(bio_err,"invalid IP address\n"); 510193267Sjkim goto err; 51167754Smsmith } 512167802Sjkim ip[0]=in[0]; 513167802Sjkim ip[1]=in[1]; 514193267Sjkim ip[2]=in[2]; 51567754Smsmith ip[3]=in[3]; 51667754Smsmith } 51767754Smsmith else 51867754Smsmith { /* do a gethostbyname */ 51967754Smsmith struct hostent *he; 520167802Sjkim 52167754Smsmith if (!ssl_sock_init()) return(0); 522167802Sjkim 523167802Sjkim he=GetHostByName(str); 52467754Smsmith if (he == NULL) 525167802Sjkim { 52667754Smsmith BIO_printf(bio_err,"gethostbyname failure\n"); 527167802Sjkim goto err; 528167802Sjkim } 52967754Smsmith /* cast to short because of win16 winsock definition */ 530167802Sjkim if ((short)he->h_addrtype != AF_INET) 531167802Sjkim { 532167802Sjkim BIO_printf(bio_err,"gethostbyname addr is not AF_INET\n"); 53367754Smsmith return(0); 53467754Smsmith } 535167802Sjkim ip[0]=he->h_addr_list[0][0]; 536167802Sjkim ip[1]=he->h_addr_list[0][1]; 537167802Sjkim ip[2]=he->h_addr_list[0][2]; 538193267Sjkim ip[3]=he->h_addr_list[0][3]; 53967754Smsmith } 540167802Sjkim return(1); 54167754Smsmitherr: 54267754Smsmith return(0); 543167802Sjkim } 544167802Sjkim 545167802Sjkimint extract_port(char *str, short *port_ptr) 546167802Sjkim { 547167802Sjkim int i; 54867754Smsmith struct servent *s; 549167802Sjkim 550167802Sjkim i=atoi(str); 551167802Sjkim if (i != 0) 552167802Sjkim *port_ptr=(unsigned short)i; 553167802Sjkim else 554167802Sjkim { 555167802Sjkim s=getservbyname(str,"tcp"); 556167802Sjkim if (s == NULL) 557167802Sjkim { 558167802Sjkim BIO_printf(bio_err,"getservbyname failure for %s\n",str); 559193267Sjkim return(0); 560193267Sjkim } 561167802Sjkim *port_ptr=ntohs((unsigned short)s->s_port); 562167802Sjkim } 56367754Smsmith return(1); 564167802Sjkim } 565167802Sjkim 566167802Sjkim#define GHBN_NUM 4 567167802Sjkimstatic struct ghbn_cache_st 56867754Smsmith { 569167802Sjkim char name[128]; 570193267Sjkim struct hostent ent; 571193267Sjkim unsigned long order; 572167802Sjkim } ghbn_cache[GHBN_NUM]; 57367754Smsmith 574167802Sjkimstatic unsigned long ghbn_hits=0L; 575167802Sjkimstatic unsigned long ghbn_miss=0L; 57667754Smsmith 57767754Smsmithstatic struct hostent *GetHostByName(char *name) 57867754Smsmith { 57967754Smsmith struct hostent *ret; 580151937Sjkim int i,lowi=0; 581151937Sjkim unsigned long low= (unsigned long)-1; 582167802Sjkim 583151937Sjkim for (i=0; i<GHBN_NUM; i++) 584167802Sjkim { 585151937Sjkim if (low > ghbn_cache[i].order) 586167802Sjkim { 587151937Sjkim low=ghbn_cache[i].order; 588167802Sjkim lowi=i; 589167802Sjkim } 590167802Sjkim if (ghbn_cache[i].order > 0) 591167802Sjkim { 592167802Sjkim if (strncmp(name,ghbn_cache[i].name,128) == 0) 593167802Sjkim break; 594167802Sjkim } 595151937Sjkim } 596151937Sjkim if (i == GHBN_NUM) /* no hit*/ 597151937Sjkim { 598167802Sjkim ghbn_miss++; 599193267Sjkim ret=gethostbyname(name); 600151937Sjkim if (ret == NULL) return(NULL); 601167802Sjkim /* else add to cache */ 602193267Sjkim if(strlen(name) < sizeof ghbn_cache[0].name) 603193267Sjkim { 604167802Sjkim strcpy(ghbn_cache[lowi].name,name); 605167802Sjkim memcpy((char *)&(ghbn_cache[lowi].ent),ret,sizeof(struct hostent)); 606167802Sjkim ghbn_cache[lowi].order=ghbn_miss+ghbn_hits; 607167802Sjkim } 608167802Sjkim return(ret); 609167802Sjkim } 610151937Sjkim else 611151937Sjkim { 612167802Sjkim ghbn_hits++; 613151937Sjkim ret= &(ghbn_cache[i].ent); 614151937Sjkim ghbn_cache[i].order=ghbn_miss+ghbn_hits; 615167802Sjkim return(ret); 616167802Sjkim } 617167802Sjkim } 618167802Sjkim 619167802Sjkim#endif 620151937Sjkim