~ubuntu-branches/ubuntu/jaunty/stunnel4/jaunty

« back to all changes in this revision

Viewing changes to src/stunnel.c

  • Committer: Bazaar Package Importer
  • Author(s): Julien Lemoine
  • Date: 2005-04-20 21:07:50 UTC
  • mfrom: (1.1.1 upstream) (2.1.1 hoary)
  • Revision ID: james.westby@ubuntu.com-20050420210750-0vk5fj5vh75o4d00
Tags: 2:4.090-1
* New upstream release
* include better stunnel3 compability script from upstream, options 
  like -cd can now be use instead of -c -d ...
  (closes: #305259)
* Added depends on perl-modules to allow use of stunnel3 compatibilty script

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 *   stunnel       Universal SSL tunnel
3
 
 *   Copyright (c) 1998-2004 Michal Trojnara <Michal.Trojnara@mirt.net>
 
3
 *   Copyright (c) 1998-2005 Michal Trojnara <Michal.Trojnara@mirt.net>
4
4
 *                 All Rights Reserved
5
5
 *
6
 
 *   Version:      4.05             (stunnel.c)
7
 
 *   Date:         2004.02.14
 
6
 *   Version:      4.09             (stunnel.c)
 
7
 *   Date:         2005.03.26
8
8
 *
9
9
 *   Author:       Michal Trojnara  <Michal.Trojnara@mirt.net>
10
10
 *
46
46
static void create_pid(void);
47
47
static void delete_pid(void);
48
48
#endif
49
 
static void setnonblock(int, unsigned long);
50
49
 
51
50
    /* Error/exceptions handling functions */
52
51
#ifndef USE_WIN32
63
62
    main_initialize(argc>1 ? argv[1] : NULL, argc>2 ? argv[2] : NULL);
64
63
 
65
64
    signal(SIGPIPE, SIG_IGN); /* avoid 'broken pipe' signal */
66
 
    signal(SIGTERM, signal_handler);
67
 
    signal(SIGQUIT, signal_handler);
68
 
    signal(SIGINT, signal_handler);
69
 
    signal(SIGHUP, signal_handler);
 
65
    if(signal(SIGTERM, SIG_IGN)!=SIG_IGN)
 
66
        signal(SIGTERM, signal_handler);
 
67
    if(signal(SIGQUIT, SIG_IGN)!=SIG_IGN)
 
68
        signal(SIGQUIT, signal_handler);
 
69
    if(signal(SIGINT, SIG_IGN)!=SIG_IGN)
 
70
        signal(SIGINT, signal_handler);
 
71
    if(signal(SIGHUP, SIG_IGN)!=SIG_IGN)
 
72
        signal(SIGHUP, signal_handler);
70
73
    /* signal(SIGSEGV, signal_handler); */
71
74
 
72
75
    main_execute();
81
84
    sthreads_init(); /* initialize critical sections & SSL callbacks */
82
85
    parse_config(arg1, arg2);
83
86
    log_open();
84
 
    log(LOG_NOTICE, "%s", stunnel_info());
 
87
    s_log(LOG_NOTICE, "%s", stunnel_info());
85
88
 
86
89
    /* check if certificate exists */
87
90
    if(!options.key) /* key file not specified */
93
96
        }
94
97
#ifndef USE_WIN32
95
98
        if(st.st_mode & 7)
96
 
            log(LOG_WARNING, "Wrong permissions on %s", options.key);
 
99
            s_log(LOG_WARNING, "Wrong permissions on %s", options.key);
97
100
#endif /* defined USE_WIN32 */
98
101
    }
99
102
}
100
103
 
101
104
void main_execute(void) {
 
105
    ssl_init(); /* initialize SSL library */
102
106
    context_init(); /* initialize global SSL context */
103
107
    /* check if started from inetd */
104
108
    if(local_options.next) { /* there are service sections -> daemon mode */
117
121
}
118
122
 
119
123
static void daemon_loop(void) {
120
 
    struct sockaddr_in addr;
121
 
    fd_set base_set, current_set;
122
 
    int n;
 
124
    SOCKADDR_UNION addr;
 
125
    s_poll_set fds;
123
126
    LOCAL_OPTIONS *opt;
124
127
 
125
128
    get_limits();
126
 
    FD_ZERO(&base_set);
 
129
    s_poll_zero(&fds);
 
130
#ifndef USE_WIN32
 
131
    s_poll_add(&fds, signal_pipe_init(), 1, 0);
 
132
#endif
 
133
 
127
134
    if(!local_options.next) {
128
 
        log(LOG_ERR, "No connections defined in config file");
 
135
        s_log(LOG_ERR, "No connections defined in config file");
129
136
        exit(1);
130
137
    }
131
138
 
132
139
    num_clients=0;
133
140
 
134
141
    /* bind local ports */
135
 
    n=0;
136
142
    for(opt=local_options.next; opt; opt=opt->next) {
137
143
        if(!opt->option.accept) /* no need to bind this service */
138
144
            continue;
139
 
        if((opt->fd=socket(AF_INET, SOCK_STREAM, 0))<0) {
 
145
        memcpy(&addr, &opt->local_addr.addr[0], sizeof(SOCKADDR_UNION));
 
146
        if((opt->fd=socket(addr.sa.sa_family, SOCK_STREAM, 0))<0) {
140
147
            sockerror("local socket");
141
148
            exit(1);
142
149
        }
144
151
            exit(1);
145
152
        if(set_socket_options(opt->fd, 0)<0)
146
153
            exit(1);
147
 
        memset(&addr, 0, sizeof(addr));
148
 
        addr.sin_family=AF_INET;
149
 
        addr.sin_addr.s_addr=*opt->localnames;
150
 
        addr.sin_port=opt->localport;
151
 
        safe_ntoa(opt->local_address, addr.sin_addr);
152
 
        if(bind(opt->fd, (struct sockaddr *)&addr, sizeof(addr))) {
153
 
            log(LOG_ERR, "Error binding %s to %s:%d", opt->servname,
154
 
                opt->local_address, ntohs(addr.sin_port));
 
154
        s_ntop(opt->local_address, &addr);
 
155
        if(bind(opt->fd, &addr.sa, addr_len(addr))) {
 
156
            s_log(LOG_ERR, "Error binding %s to %s",
 
157
                opt->servname, opt->local_address);
155
158
            sockerror("bind");
156
159
            exit(1);
157
160
        }
158
 
        log(LOG_DEBUG, "%s bound to %s:%d", opt->servname,
159
 
            opt->local_address, ntohs(addr.sin_port));
 
161
        s_log(LOG_DEBUG, "%s bound to %s", opt->servname, opt->local_address);
160
162
        if(listen(opt->fd, 5)) {
161
163
            sockerror("listen");
162
164
            exit(1);
164
166
#ifdef FD_CLOEXEC
165
167
        fcntl(opt->fd, F_SETFD, FD_CLOEXEC); /* close socket in child execvp */
166
168
#endif
167
 
        FD_SET(opt->fd, &base_set);
168
 
        if(opt->fd > n)
169
 
            n=opt->fd;
 
169
        s_poll_add(&fds, opt->fd, 1, 0);
170
170
    }
171
171
 
172
 
#ifndef USE_WIN32
173
 
    sselect_init(&base_set, &n);
174
 
#endif
175
 
 
176
172
#if !defined (USE_WIN32) && !defined (__vms)
177
173
    if(!(options.option.foreground))
178
174
        daemonize();
191
187
    }
192
188
 
193
189
    while(1) {
194
 
        memcpy(&current_set, &base_set, sizeof(fd_set));
195
 
        if(sselect(n+1, &current_set, NULL, NULL, NULL)<0)
196
 
            /* non-critical error */
197
 
            log_error(LOG_INFO, get_last_socket_error(), "main loop select");
 
190
        if(s_poll_wait(&fds, -1)<0) /* non-critical error */
 
191
            log_error(LOG_INFO, get_last_socket_error(),
 
192
                "daemon_loop: s_poll_wait");
198
193
        else 
199
194
            for(opt=local_options.next; opt; opt=opt->next)
200
 
                if(FD_ISSET(opt->fd, &current_set))
 
195
                if(s_poll_canread(&fds, opt->fd))
201
196
                    accept_connection(opt);
202
197
    }
203
 
    log(LOG_ERR, "INTERNAL ERROR: End of infinite loop 8-)");
 
198
    s_log(LOG_ERR, "INTERNAL ERROR: End of infinite loop 8-)");
204
199
}
205
200
 
206
201
static void accept_connection(LOCAL_OPTIONS *opt) {
207
 
    struct sockaddr_in addr;
208
 
    int err, s, addrlen=sizeof(addr);
 
202
    SOCKADDR_UNION addr;
 
203
    char from_address[IPLEN];
 
204
    int s, addrlen=sizeof(SOCKADDR_UNION);
209
205
 
210
 
    do {
211
 
        s=accept(opt->fd, (struct sockaddr *)&addr, &addrlen);
212
 
        if(s<0)
213
 
            err=get_last_socket_error();
214
 
    } while(s<0 && err==EINTR);
215
 
    if(s<0) {
216
 
        sockerror("accept");
217
 
        switch(err) {
 
206
    while((s=accept(opt->fd, &addr.sa, &addrlen))<0) {
 
207
        switch(get_last_socket_error()) {
 
208
            case EINTR:
 
209
                break; /* retry */
218
210
            case EMFILE:
219
211
            case ENFILE:
220
212
#ifdef ENOBUFS
221
213
            case ENOBUFS:
222
214
#endif
223
215
            case ENOMEM:
224
 
                sleep(1);
 
216
                sleep(1); /* temporarily out of resources - short delay */
225
217
            default:
226
 
                ;
 
218
                sockerror("accept");
 
219
                return; /* error */
227
220
        }
228
 
        return;
229
221
    }
230
 
    enter_critical_section(CRIT_NTOA); /* inet_ntoa is not mt-safe */
231
 
    log(LOG_DEBUG, "%s accepted FD=%d from %s:%d", opt->servname, s,
232
 
        inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
233
 
    leave_critical_section(CRIT_NTOA);
234
 
    if(num_clients>=max_clients) {
235
 
        log(LOG_WARNING, "Connection rejected: too many clients (>=%d)",
 
222
    s_ntop(from_address, &addr);
 
223
    s_log(LOG_DEBUG, "%s accepted FD=%d from %s",
 
224
        opt->servname, s, from_address);
 
225
    if(max_clients && num_clients>=max_clients) {
 
226
        s_log(LOG_WARNING, "Connection rejected: too many clients (>=%d)",
236
227
            max_clients);
237
228
        closesocket(s);
238
229
        return;
243
234
    fcntl(s, F_SETFD, FD_CLOEXEC); /* close socket in child execvp */
244
235
#endif
245
236
    if(create_client(opt->fd, s, alloc_client_session(opt, s, s), client)) {
246
 
        log(LOG_ERR, "Connection rejected: create_client failed");
 
237
        s_log(LOG_ERR, "Connection rejected: create_client failed");
247
238
        closesocket(s);
248
239
        return;
249
240
    }
254
245
 
255
246
static void get_limits(void) {
256
247
#ifdef USE_WIN32
257
 
    max_clients=30000;
258
 
    log(LOG_NOTICE, "WIN32 platform: %d clients allowed", max_clients);
 
248
    max_clients=0;
 
249
    s_log(LOG_NOTICE, "No limit detected for the number of clients");
259
250
#else
260
 
    int fds_ulimit=-1;
 
251
    max_fds=0; /* unlimited */
261
252
 
262
253
#if defined HAVE_SYSCONF
263
 
    fds_ulimit=sysconf(_SC_OPEN_MAX);
264
 
    if(fds_ulimit<0)
 
254
    max_fds=sysconf(_SC_OPEN_MAX);
 
255
    if(max_fds<0)
265
256
        ioerror("sysconf");
266
257
#elif defined HAVE_GETRLIMIT
267
258
    struct rlimit rlim;
268
259
    if(getrlimit(RLIMIT_NOFILE, &rlim)<0)
269
260
        ioerror("getrlimit");
270
261
    else
271
 
        fds_ulimit=rlim.rlim_cur;
272
 
    if(fds_ulimit==RLIM_INFINITY)
273
 
        fds_ulimit=-1;
274
 
#endif
275
 
    max_fds=fds_ulimit<FD_SETSIZE ? fds_ulimit : FD_SETSIZE;
276
 
    if(max_fds<16) /* stunnel needs at least 16 file desriptors to work */
 
262
        max_fds=rlim.rlim_cur;
 
263
    if(max_fds==RLIM_INFINITY)
 
264
        max_fds=0; /* RLIM_INFINITY should be equal to zero, anyway */
 
265
#endif
 
266
    s_log(LOG_INFO, "file ulimit = %d%s (can be changed with 'ulimit -n')",
 
267
        max_fds, max_fds ? "" : " (unlimited)");
 
268
#ifdef HAVE_POLL
 
269
    s_log(LOG_INFO, "poll() used - no FD_SETSIZE limit for file descriptors");
 
270
#else
 
271
    s_log(LOG_INFO,
 
272
        "FD_SETSIZE = %d (some systems allow to increase this value)",
 
273
        FD_SETSIZE);
 
274
    if(!max_fds || max_fds>FD_SETSIZE)
 
275
        max_fds=FD_SETSIZE;
 
276
#endif
 
277
    if(max_fds && max_fds<16) /* stunnel needs at least 16 file desriptors */
277
278
        max_fds=16;
278
 
    max_clients=max_fds>=256 ? max_fds*125/256 : (max_fds-6)/2;
279
 
    log(LOG_NOTICE, "FD_SETSIZE=%d, file ulimit=%d%s -> %d clients allowed",
280
 
        FD_SETSIZE, fds_ulimit, fds_ulimit<0?" (unlimited)":"", max_clients);
 
279
    if(max_fds) {
 
280
        max_clients=max_fds>=256 ? max_fds*125/256 : (max_fds-6)/2;
 
281
        s_log(LOG_NOTICE, "%d clients allowed", max_clients);
 
282
    } else {
 
283
        max_clients=0;
 
284
        s_log(LOG_NOTICE, "No limit detected for the number of clients");
 
285
    }
281
286
#endif
282
287
}
283
288
 
299
304
        else if(atoi(options.setgid_group)) /* numerical? */
300
305
            gid=atoi(options.setgid_group);
301
306
        else {
302
 
            log(LOG_ERR, "Failed to get GID for group %s",
 
307
            s_log(LOG_ERR, "Failed to get GID for group %s",
303
308
                options.setgid_group);
304
309
            exit(1);
305
310
        }
311
316
        else if(atoi(options.setuid_user)) /* numerical? */
312
317
            uid=atoi(options.setuid_user);
313
318
        else {
314
 
            log(LOG_ERR, "Failed to get UID for user %s",
 
319
            s_log(LOG_ERR, "Failed to get UID for user %s",
315
320
                options.setuid_user);
316
321
            exit(1);
317
322
        }
355
360
 
356
361
static void daemonize(void) { /* go to background */
357
362
#if defined(HAVE_DAEMON) && !defined(__BEOS__)
358
 
    if(daemon(0,0)==-1){
 
363
    if(daemon(0,0)==-1) {
359
364
        ioerror("daemon");
360
365
        exit(1);
361
366
    }
384
389
    char pid[STRLEN];
385
390
 
386
391
    if(!options.pidfile) {
387
 
        log(LOG_DEBUG, "No pid file being created");
 
392
        s_log(LOG_DEBUG, "No pid file being created");
388
393
        return;
389
394
    }
390
395
    if(options.pidfile[0]!='/') {
391
 
        log(LOG_ERR, "Pid file (%s) must be full path name", options.pidfile);
 
396
        s_log(LOG_ERR, "Pid file (%s) must be full path name", options.pidfile);
392
397
        /* Why?  Because we don't want to confuse by
393
398
           allowing '.', which would be '/' after
394
399
           daemonizing) */
399
404
    /* silently remove old pid file */
400
405
    unlink(options.pidfile);
401
406
    if((pf=open(options.pidfile, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL,0644))==-1) {
402
 
        log(LOG_ERR, "Cannot create pid file %s", options.pidfile);
 
407
        s_log(LOG_ERR, "Cannot create pid file %s", options.pidfile);
403
408
        ioerror("create");
404
409
        exit(1);
405
410
    }
406
411
    sprintf(pid, "%lu\n", options.dpid);
407
412
    write(pf, pid, strlen(pid));
408
413
    close(pf);
409
 
    log(LOG_DEBUG, "Created pid file %s", options.pidfile);
 
414
    s_log(LOG_DEBUG, "Created pid file %s", options.pidfile);
410
415
    atexit(delete_pid);
411
416
}
412
417
 
413
418
static void delete_pid(void) {
414
 
    log(LOG_DEBUG, "removing pid file %s", options.pidfile);
 
419
    s_log(LOG_DEBUG, "removing pid file %s", options.pidfile);
415
420
    if((unsigned long)getpid()!=options.dpid)
416
421
        return; /* current process is not main daemon process */
417
422
    if(unlink(options.pidfile)<0)
418
423
        ioerror(options.pidfile); /* not critical */
419
424
}
420
 
#endif /* defined USE_WIN32 */
421
 
 
422
 
int set_socket_options(int s, int type) {
423
 
    SOCK_OPT *ptr;
424
 
    extern SOCK_OPT sock_opts[];
425
 
    static char *type_str[3]={"accept", "local", "remote"};
426
 
    int opt_size;
427
 
 
428
 
    for(ptr=sock_opts;ptr->opt_str;ptr++) {
429
 
        if(!ptr->opt_val[type])
430
 
            continue; /* default */
431
 
        switch(ptr->opt_type) {
432
 
        case TYPE_LINGER:
433
 
            opt_size=sizeof(struct linger); break;
434
 
        case TYPE_TIMEVAL:
435
 
            opt_size=sizeof(struct timeval); break;
436
 
        case TYPE_STRING:
437
 
            opt_size=strlen(ptr->opt_val[type]->c_val)+1; break;
438
 
        default:
439
 
            opt_size=sizeof(int); break;
440
 
        }
441
 
        if(setsockopt(s, ptr->opt_level, ptr->opt_name,
442
 
                (void *)ptr->opt_val[type], opt_size)) {
443
 
            sockerror(ptr->opt_str);
444
 
            return -1; /* FAILED */
445
 
        } else {
446
 
            log(LOG_DEBUG, "%s option set on %s socket",
447
 
                ptr->opt_str, type_str[type]);
448
 
        }
449
 
    }
450
 
    return 0; /* OK */
451
 
}
452
 
 
453
 
void ioerror(char *txt) { /* input/output error handler */
454
 
    log_error(LOG_ERR, get_last_error(), txt);
455
 
}
456
 
 
457
 
void sockerror(char *txt) { /* socket error handler */
458
 
    log_error(LOG_ERR, get_last_socket_error(), txt);
459
 
}
460
 
 
461
 
void log_error(int level, int error, char *txt) { /* generic error logger */
462
 
    log(level, "%s: %s (%d)", txt, my_strerror(error), error);
463
 
}
464
 
 
465
 
char *my_strerror(int errnum) {
466
 
    switch(errnum) {
467
 
#ifdef USE_WIN32
468
 
    case 10004:
469
 
        return "Interrupted system call (WSAEINTR)";
470
 
    case 10009:
471
 
        return "Bad file number (WSAEBADF)";
472
 
    case 10013:
473
 
        return "Permission denied (WSAEACCES)";
474
 
    case 10014:
475
 
        return "Bad address (WSAEFAULT)";
476
 
    case 10022:
477
 
        return "Invalid argument (WSAEINVAL)";
478
 
    case 10024:
479
 
        return "Too many open files (WSAEMFILE)";
480
 
    case 10035:
481
 
        return "Operation would block (WSAEWOULDBLOCK)";
482
 
    case 10036:
483
 
        return "Operation now in progress (WSAEINPROGRESS)";
484
 
    case 10037:
485
 
        return "Operation already in progress (WSAEALREADY)";
486
 
    case 10038:
487
 
        return "Socket operation on non-socket (WSAENOTSOCK)";
488
 
    case 10039:
489
 
        return "Destination address required (WSAEDESTADDRREQ)";
490
 
    case 10040:
491
 
        return "Message too long (WSAEMSGSIZE)";
492
 
    case 10041:
493
 
        return "Protocol wrong type for socket (WSAEPROTOTYPE)";
494
 
    case 10042:
495
 
        return "Bad protocol option (WSAENOPROTOOPT)";
496
 
    case 10043:
497
 
        return "Protocol not supported (WSAEPROTONOSUPPORT)";
498
 
    case 10044:
499
 
        return "Socket type not supported (WSAESOCKTNOSUPPORT)";
500
 
    case 10045:
501
 
        return "Operation not supported on socket (WSAEOPNOTSUPP)";
502
 
    case 10046:
503
 
        return "Protocol family not supported (WSAEPFNOSUPPORT)";
504
 
    case 10047:
505
 
        return "Address family not supported by protocol family (WSAEAFNOSUPPORT)";
506
 
    case 10048:
507
 
        return "Address already in use (WSAEADDRINUSE)";
508
 
    case 10049:
509
 
        return "Can't assign requested address (WSAEADDRNOTAVAIL)";
510
 
    case 10050:
511
 
        return "Network is down (WSAENETDOWN)";
512
 
    case 10051:
513
 
        return "Network is unreachable (WSAENETUNREACH)";
514
 
    case 10052:
515
 
        return "Net dropped connection or reset (WSAENETRESET)";
516
 
    case 10053:
517
 
        return "Software caused connection abort (WSAECONNABORTED)";
518
 
    case 10054:
519
 
        return "Connection reset by peer (WSAECONNRESET)";
520
 
    case 10055:
521
 
        return "No buffer space available (WSAENOBUFS)";
522
 
    case 10056:
523
 
        return "Socket is already connected (WSAEISCONN)";
524
 
    case 10057:
525
 
        return "Socket is not connected (WSAENOTCONN)";
526
 
    case 10058:
527
 
        return "Can't send after socket shutdown (WSAESHUTDOWN)";
528
 
    case 10059:
529
 
        return "Too many references, can't splice (WSAETOOMANYREFS)";
530
 
    case 10060:
531
 
        return "Connection timed out (WSAETIMEDOUT)";
532
 
    case 10061:
533
 
        return "Connection refused (WSAECONNREFUSED)";
534
 
    case 10062:
535
 
        return "Too many levels of symbolic links (WSAELOOP)";
536
 
    case 10063:
537
 
        return "File name too long (WSAENAMETOOLONG)";
538
 
    case 10064:
539
 
        return "Host is down (WSAEHOSTDOWN)";
540
 
    case 10065:
541
 
        return "No Route to Host (WSAEHOSTUNREACH)";
542
 
    case 10066:
543
 
        return "Directory not empty (WSAENOTEMPTY)";
544
 
    case 10067:
545
 
        return "Too many processes (WSAEPROCLIM)";
546
 
    case 10068:
547
 
        return "Too many users (WSAEUSERS)";
548
 
    case 10069:
549
 
        return "Disc Quota Exceeded (WSAEDQUOT)";
550
 
    case 10070:
551
 
        return "Stale NFS file handle (WSAESTALE)";
552
 
    case 10091:
553
 
        return "Network SubSystem is unavailable (WSASYSNOTREADY)";
554
 
    case 10092:
555
 
        return "WINSOCK DLL Version out of range (WSAVERNOTSUPPORTED)";
556
 
    case 10093:
557
 
        return "Successful WSASTARTUP not yet performed (WSANOTINITIALISED)";
558
 
    case 10071:
559
 
        return "Too many levels of remote in path (WSAEREMOTE)";
560
 
    case 11001:
561
 
        return "Host not found (WSAHOST_NOT_FOUND)";
562
 
    case 11002:
563
 
        return "Non-Authoritative Host not found (WSATRY_AGAIN)";
564
 
    case 11003:
565
 
        return "Non-Recoverable errors: FORMERR, REFUSED, NOTIMP (WSANO_RECOVERY)";
566
 
    case 11004:
567
 
        return "Valid name, no data record of requested type (WSANO_DATA)";
568
 
#if 0
569
 
    case 11004: /* typically, only WSANO_DATA is reported */
570
 
        return "No address, look for MX record (WSANO_ADDRESS)";
571
 
#endif
572
 
#endif /* defined USE_WIN32 */
573
 
    default:
574
 
        return strerror(errnum);
575
 
    }
576
 
}
577
 
 
578
 
#ifndef USE_WIN32
579
425
 
580
426
static void signal_handler(int sig) { /* signal handler */
581
 
    log(sig==SIGTERM ? LOG_NOTICE : LOG_ERR,
 
427
    s_log(sig==SIGTERM ? LOG_NOTICE : LOG_ERR,
582
428
        "Received signal %d; terminating", sig);
583
429
    exit(3);
584
430
}
585
 
 
586
431
#endif /* !defined USE_WIN32 */
587
432
 
588
433
char *stunnel_info(void) {
598
443
#ifdef USE_FORK
599
444
    safeconcat(retval, " FORK");
600
445
#endif
 
446
#ifdef HAVE_POLL
 
447
    safeconcat(retval, "+POLL");
 
448
#endif
 
449
#ifdef USE_WIN32
 
450
    if(s_getaddrinfo)
 
451
        safeconcat(retval, "+IPv6");
 
452
    else
 
453
        safeconcat(retval, "+IPv4");
 
454
#else /* defined(USE_WIN32) */
 
455
#if defined(USE_IPv6)
 
456
    safeconcat(retval, "+IPv6");
 
457
#else /* defined(USE_IPv6) */
 
458
    safeconcat(retval, "+IPv4");
 
459
#endif /* defined(USE_IPv6) */
 
460
#endif /* defined(USE_WIN32) */
601
461
#ifdef USE_LIBWRAP
602
462
    safeconcat(retval, "+LIBWRAP");
603
463
#endif
606
466
    return retval;
607
467
}
608
468
 
609
 
int alloc_fd(int sock) {
610
 
#ifndef USE_WIN32
611
 
    if(sock>=max_fds) {
612
 
        log(LOG_ERR,
613
 
            "File descriptor out of range (%d>=%d)", sock, max_fds);
614
 
        closesocket(sock);
615
 
        return -1;
616
 
    }
617
 
#endif
618
 
    setnonblock(sock, 1);
619
 
    return 0;
620
 
}
621
 
 
622
 
/* Try to use non-POSIX O_NDELAY on obsolete BSD systems */
623
 
#if !defined O_NONBLOCK && defined O_NDELAY
624
 
#define O_NONBLOCK O_NDELAY
625
 
#endif
626
 
 
627
 
static void setnonblock(int sock, unsigned long l) {
628
 
#if defined F_GETFL && defined F_SETFL && defined O_NONBLOCK
629
 
    int retval, flags;
630
 
    do {
631
 
        flags=fcntl(sock, F_GETFL, 0);
632
 
    }while(flags<0 && errno==EINTR);
633
 
    flags=l ? flags|O_NONBLOCK : flags&(~O_NONBLOCK);
634
 
    do {
635
 
        retval=fcntl(sock, F_SETFL, flags);
636
 
    }while(retval<0 && errno==EINTR);
637
 
    if(retval<0)
638
 
#else
639
 
    if(ioctlsocket(sock, FIONBIO, &l)<0)
640
 
#endif
641
 
        sockerror("nonblocking"); /* non-critical */
642
 
    else
643
 
        log(LOG_DEBUG, "FD %d in %sblocking mode", sock,
644
 
            l ? "non-" : "");
645
 
}
646
 
 
647
 
char *safe_ntoa(char *text, struct in_addr in) {
648
 
    enter_critical_section(CRIT_NTOA); /* inet_ntoa is not mt-safe */
649
 
    strncpy(text, inet_ntoa(in), 15);
650
 
    leave_critical_section(CRIT_NTOA);
651
 
    text[15]='\0';
652
 
    return text;
653
 
}
654
 
 
655
469
/* End of stunnel.c */