Coverage Report

Created: 2026-01-16 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/proftpd/src/bindings.c
Line
Count
Source
1
/*
2
 * ProFTPD - FTP server daemon
3
 * Copyright (c) 2001-2025 The ProFTPD Project team
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
18
 *
19
 * As a special exemption, The ProFTPD Project team and other respective
20
 * copyright holders give permission to link this program with OpenSSL, and
21
 * distribute the resulting executable, without including the source code for
22
 * OpenSSL in the source distribution.
23
 */
24
25
/* Routines to work with ProFTPD bindings. */
26
27
#include "conf.h"
28
29
/* From src/dirtree.c */
30
extern xaset_t *server_list;
31
extern server_rec *main_server;
32
33
static pr_ipbind_t *ipbind_table[PR_BINDINGS_TABLE_SIZE];
34
static int ipbind_table_initialized = FALSE;
35
36
static pool *binding_pool = NULL;
37
static pr_ipbind_t *ipbind_default_server = NULL,
38
                   *ipbind_localhost_server = NULL;
39
40
static const char *trace_channel = "binding";
41
42
static void trace_ipbind_table(void);
43
44
0
static void init_ipbind_table(void) {
45
0
  if (ipbind_table_initialized == TRUE) {
46
0
    return;
47
0
  }
48
49
0
  memset(ipbind_table, 0, sizeof(ipbind_table));
50
0
  ipbind_table_initialized = TRUE;
51
0
}
52
53
/* Server cleanup callback function */
54
0
static void server_cleanup_cb(void *conn) {
55
0
  *((conn_t **) conn) = NULL;
56
0
}
57
58
/* The hashing function for the hash table of bindings.  This algorithm
59
 * is stolen from Apache's http_vhost.c
60
 */
61
static unsigned int ipbind_hash_addr(const pr_netaddr_t *addr,
62
0
    unsigned int port) {
63
0
  size_t offset;
64
0
  unsigned int key, idx;
65
66
0
  offset = pr_netaddr_get_inaddr_len(addr);
67
68
  /* The key is the last four bytes of the IP address.
69
   * For IPv4, this is the entire address, as always.
70
   * For IPv6, this is usually part of the MAC address.
71
   */
72
0
  key = *(unsigned *) ((char *) pr_netaddr_get_inaddr(addr) + offset - 4);
73
74
  /* Add in the port number, to give better spread of key values when many
75
   * different port values are used.
76
   */
77
0
  key += port;
78
79
0
  key ^= (key >> 16);
80
0
  idx = ((key >> 8) ^ key) % PR_BINDINGS_TABLE_SIZE;
81
0
  return idx;
82
0
}
83
84
static pool *listening_conn_pool = NULL;
85
static xaset_t *listening_conn_list = NULL;
86
struct listener_rec {
87
  struct listener_rec *next, *prev;
88
89
  pool *pool;
90
  const pr_netaddr_t *addr;
91
  unsigned int port;
92
  conn_t *conn;
93
  int claimed;
94
};
95
96
conn_t *pr_ipbind_get_listening_conn(server_rec *server,
97
0
    const pr_netaddr_t *addr, unsigned int port) {
98
0
  conn_t *l, *sl;
99
0
  pool *p;
100
0
  struct listener_rec *lr;
101
102
0
  if (listening_conn_list) {
103
0
    for (lr = (struct listener_rec *) listening_conn_list->xas_list; lr;
104
0
        lr = lr->next) {
105
0
      int use_elt = FALSE;
106
107
0
      pr_signals_handle();
108
109
0
      if (addr != NULL &&
110
0
          lr->addr != NULL) {
111
0
        const char *lr_ipstr = NULL;
112
113
0
        lr_ipstr = pr_netaddr_get_ipstr(lr->addr);
114
115
        /* Note: lr_ipstr should never be null.  If it is, it means that
116
         * the lr->addr object never had its IP address resolved/stashed,
117
         * and in attempting to do, getnameinfo(3) failed for some reason.
118
         *
119
         * The IP address on which it's listening, if not available via
120
         * lr->addr, should thus be available via lr->conn->local_addr.
121
         */
122
123
0
        if (lr_ipstr == NULL &&
124
0
            lr->conn != NULL) {
125
0
          lr_ipstr = pr_netaddr_get_ipstr(lr->conn->local_addr);
126
0
        }
127
128
0
        if (lr_ipstr != NULL) {
129
0
          if (strcmp(pr_netaddr_get_ipstr(addr), lr_ipstr) == 0 &&
130
0
              port == lr->port) {
131
0
            use_elt = TRUE;
132
0
          }
133
0
        }
134
135
0
      } else if (addr == NULL &&
136
0
                 port == lr->port) {
137
0
        use_elt = TRUE;
138
0
      }
139
140
0
      if (use_elt == TRUE) {
141
0
        lr->claimed = TRUE;
142
0
        return lr->conn;
143
0
      }
144
0
    }
145
0
  }
146
147
0
  if (listening_conn_pool == NULL) {
148
0
    listening_conn_pool = make_sub_pool(permanent_pool);
149
0
    pr_pool_tag(listening_conn_pool, "Listening Connection Pool");
150
151
0
    listening_conn_list = xaset_create(listening_conn_pool, NULL);
152
0
  }
153
154
0
  p = make_sub_pool(listening_conn_pool);
155
0
  pr_pool_tag(p, "Listening conn subpool");
156
157
0
  l = pr_inet_create_conn(p, -1, addr, port, FALSE);
158
0
  if (l == NULL) {
159
0
    return NULL;
160
0
  }
161
162
  /* Inform any interested listeners that this socket was opened.  In order
163
   * to convey the discovered conn_t `l` to the event listener, we set it
164
   * on the server `s` temporarily.
165
   */
166
0
  sl = server->listen;
167
0
  server->listen = l;
168
0
  pr_inet_generate_socket_event("core.ctrl-listen", server, l->local_addr,
169
0
    l->listen_fd);
170
0
  server->listen = sl;
171
172
0
  lr = pcalloc(p, sizeof(struct listener_rec));
173
0
  lr->pool = p;
174
0
  lr->conn = l;
175
0
  lr->addr = pr_netaddr_dup(p, addr);
176
0
  if (lr->addr == NULL &&
177
0
      errno != EINVAL) {
178
0
    return NULL;
179
0
  }
180
0
  lr->port = port;
181
0
  lr->claimed = TRUE;
182
183
0
  xaset_insert(listening_conn_list, (xasetmember_t *) lr);
184
0
  return l;
185
0
}
186
187
/* Slight (clever?) optimization: the loop in server_loop() always
188
 * calls pr_ipbind_listen(), selects, then pr_ipbind_accept_conn().  Now,
189
 * rather than having both pr_ipbind_listen() and pr_ipbind_accept_conn()
190
 * scan the entire ipbind table looking for matches, what if pr_ipbind_listen
191
 * kept track of which listeners (connt_s) it used, so that
192
 * pr_ipbind_accept_conn() need merely check those listeners, rather than
193
 * scanning the entire table itself?
194
 */
195
196
static array_header *listener_list = NULL;
197
198
0
conn_t *pr_ipbind_accept_conn(fd_set *readfds, int *listenfd) {
199
0
  conn_t **listeners = listener_list->elts;
200
0
  register unsigned int i = 0;
201
202
0
  if (readfds == NULL ||
203
0
      listenfd == NULL) {
204
0
    errno = EINVAL;
205
0
    return NULL;
206
0
  }
207
208
0
  for (i = 0; i < listener_list->nelts; i++) {
209
0
    conn_t *listener = listeners[i];
210
211
0
    pr_signals_handle();
212
0
    if (FD_ISSET(listener->listen_fd, readfds) &&
213
0
        listener->mode == CM_LISTEN) {
214
0
      int fd = pr_inet_accept_nowait(listener->pool, listener);
215
216
0
      if (fd == -1) {
217
0
        int xerrno = errno;
218
219
        /* Handle errors gracefully.  If we're here, then
220
         * ipbind->ib_server->listen contains either error information, or
221
         * we just got caught in a blocking condition.
222
         */
223
0
        if (listener->mode == CM_ERROR) {
224
225
          /* Ignore ECONNABORTED, as they tend to be health checks/probes by
226
           * e.g. load balancers and other naive TCP clients.
227
           */
228
0
          if (listener->xerrno != ECONNABORTED) {
229
0
            pr_log_pri(PR_LOG_ERR, "error: unable to accept an incoming "
230
0
              "connection: %s", strerror(listener->xerrno));
231
0
          }
232
233
0
          listener->xerrno = 0;
234
0
          listener->mode = CM_LISTEN;
235
236
0
          errno = xerrno;
237
0
          return NULL;
238
0
        }
239
0
      }
240
241
0
      *listenfd = fd;
242
0
      return listener;
243
0
    }
244
0
  }
245
246
0
  errno = ENOENT;
247
0
  return NULL;
248
0
}
249
250
0
int pr_ipbind_add_binds(server_rec *serv) {
251
0
  int res = 0;
252
0
  config_rec *c = NULL;
253
0
  conn_t *listen_conn = NULL;
254
0
  const pr_netaddr_t *addr = NULL;
255
256
0
  if (serv == NULL) {
257
0
    errno = EINVAL;
258
0
    return -1;
259
0
  }
260
261
0
  c = find_config(serv->conf, CONF_PARAM, "_bind_", FALSE);
262
0
  while (c != NULL) {
263
0
    listen_conn = NULL;
264
265
0
    pr_signals_handle();
266
267
0
    addr = pr_netaddr_get_addr(serv->pool, c->argv[0], NULL);
268
0
    if (addr == NULL) {
269
0
      pr_log_pri(PR_LOG_WARNING,
270
0
       "notice: unable to determine IP address of '%s'", (char *) c->argv[0]);
271
0
      c = find_config_next(c, c->next, CONF_PARAM, "_bind_", FALSE);
272
0
      continue;
273
0
    }
274
275
    /* If the SocketBindTight directive is in effect, create a separate
276
     * listen socket for this address, and add it to the binding list.
277
     */
278
0
    if (SocketBindTight &&
279
0
        serv->ServerPort) {
280
0
      listen_conn = pr_ipbind_get_listening_conn(serv, addr, serv->ServerPort);
281
0
      if (listen_conn == NULL) {
282
0
        return -1;
283
0
      }
284
285
0
      res = pr_ipbind_create(serv, addr, serv->ServerPort);
286
0
      if (res < 0) {
287
0
        pr_log_pri(PR_LOG_NOTICE,
288
0
          "%s:%d: notice: unable to create ipbind '%s#%u': %s", __FILE__,
289
0
          __LINE__, serv->ServerAddress, serv->ServerPort, strerror(errno));
290
0
      }
291
292
0
      res = pr_ipbind_open(addr, serv->ServerPort, listen_conn, FALSE, FALSE,
293
0
        TRUE);
294
0
      if (res < 0) {
295
0
        pr_log_pri(PR_LOG_NOTICE,
296
0
          "%s:%d: notice: unable to open ipbind '%s': %s", __FILE__, __LINE__,
297
0
          pr_netaddr_get_ipstr(addr), strerror(errno));
298
0
      }
299
300
0
    } else {
301
0
      res = pr_ipbind_create(serv, addr, serv->ServerPort);
302
0
      if (res < 0) {
303
0
        pr_log_pri(PR_LOG_NOTICE,
304
0
          "%s:%d: notice: unable to create ipbind '%s#%u': %s", __FILE__,
305
0
          __LINE__, serv->ServerAddress, serv->ServerPort, strerror(errno));
306
0
      }
307
308
0
      res = pr_ipbind_open(addr, serv->ServerPort, serv->listen, FALSE, FALSE,
309
0
        TRUE);
310
0
      if (res < 0) {
311
0
        pr_log_pri(PR_LOG_NOTICE,
312
0
          "%s:%d: notice: unable to open ipbind '%s': %s", __FILE__, __LINE__,
313
0
          pr_netaddr_get_ipstr(addr), strerror(errno));
314
0
      }
315
0
    }
316
317
0
    c = find_config_next(c, c->next, CONF_PARAM, "_bind_", FALSE);
318
0
  }
319
320
0
  return 0;
321
0
}
322
323
int pr_ipbind_close(const pr_netaddr_t *addr, unsigned int port,
324
0
    unsigned char close_namebinds) {
325
0
  register unsigned int i = 0;
326
327
0
  if (addr != NULL) {
328
0
    pr_ipbind_t *ipbind = NULL;
329
0
    unsigned char have_ipbind = FALSE;
330
331
0
    i = ipbind_hash_addr(addr, port);
332
333
0
    if (ipbind_table[i] == NULL) {
334
0
      pr_log_pri(PR_LOG_NOTICE, "notice: no ipbind found for %s:%d",
335
0
        pr_netaddr_get_ipstr(addr), port);
336
0
      errno = ENOENT;
337
0
      return -1;
338
0
    }
339
340
0
    for (ipbind = ipbind_table[i]; ipbind; ipbind = ipbind->ib_next) {
341
0
      pr_signals_handle();
342
343
0
      if (pr_netaddr_cmp(ipbind->ib_addr, addr) == 0 &&
344
0
          (!ipbind->ib_port || ipbind->ib_port == port)) {
345
0
        have_ipbind = TRUE;
346
0
        break;
347
0
      }
348
0
    }
349
350
0
    if (have_ipbind == FALSE) {
351
0
      pr_log_pri(PR_LOG_NOTICE, "notice: no ipbind found for %s:%d",
352
0
        pr_netaddr_get_ipstr(addr), port);
353
0
      errno = ENOENT;
354
0
      return -1;
355
0
    }
356
357
    /* If already closed, exit now. */
358
0
    if (ipbind->ib_isactive == FALSE) {
359
0
      errno = EPERM;
360
0
      return -1;
361
0
    }
362
363
    /* Close the ipbinding's listen connection, if present.  The trick
364
     * here is determining whether this binding's listen member is
365
     * _the_ listening socket for the master daemon, or whether it's
366
     * been created for SocketBindTight, and can be closed.
367
     *
368
     * Actually, it's not that hard.  It's only _the_ listening socket
369
     * for the master daemon in inetd mode, in which case virtual servers
370
     * can't be shutdown via ftpdctl, anyway.
371
     */
372
0
    if (SocketBindTight &&
373
0
        ipbind->ib_listener != NULL) {
374
0
      pr_inet_close(ipbind->ib_server->pool, ipbind->ib_listener);
375
0
      ipbind->ib_listener = ipbind->ib_server->listen = NULL;
376
0
    }
377
378
    /* Mark this ipbind as inactive.  For SocketBindTight sockets, the
379
     * closing of the listening connection will suffice, from the clients'
380
     * point of view.  However, this covers the non-SocketBindTight case,
381
     * and will prevent this binding from returning its server_rec pointer
382
     * on future lookup requests via pr_ipbind_get_server().
383
     */
384
0
    ipbind->ib_isactive = FALSE;
385
386
0
    if (close_namebinds == TRUE &&
387
0
        ipbind->ib_namebinds != NULL) {
388
0
      register unsigned int j = 0;
389
0
      pr_namebind_t **namebinds = NULL;
390
391
0
      namebinds = (pr_namebind_t **) ipbind->ib_namebinds->elts;
392
0
      for (j = 0; j < ipbind->ib_namebinds->nelts; j++) {
393
0
        pr_namebind_t *nb;
394
395
0
        pr_signals_handle();
396
397
0
        nb = namebinds[j];
398
0
        if (pr_namebind_close(nb->nb_name, nb->nb_server->addr) < 0) {
399
0
          pr_trace_msg(trace_channel, 7,
400
0
            "notice: error closing namebind '%s' for address %s: %s",
401
0
            nb->nb_name, pr_netaddr_get_ipstr(nb->nb_server->addr),
402
0
            strerror(errno));
403
0
        }
404
0
      }
405
0
    }
406
407
0
  } else {
408
    /* A NULL addr has a special meaning: close _all_ ipbinds in the list. */
409
0
    for (i = 0; i < PR_BINDINGS_TABLE_SIZE; i++) {
410
0
      pr_ipbind_t *ipbind = NULL;
411
412
0
      pr_signals_handle();
413
414
0
      for (ipbind = ipbind_table[i]; ipbind; ipbind = ipbind->ib_next) {
415
0
        if (SocketBindTight &&
416
0
            ipbind->ib_listener != NULL) {
417
0
          pr_inet_close(main_server->pool, ipbind->ib_listener);
418
0
          ipbind->ib_listener = ipbind->ib_server->listen = NULL;
419
0
        }
420
421
        /* Note: do not need to check if this ipbind was previously closed,
422
         * for the NULL addr is a request to shut down all ipbinds,
423
         * regardless of their current state.
424
         */
425
0
        ipbind->ib_isactive = FALSE;
426
427
0
        if (close_namebinds &&
428
0
            ipbind->ib_namebinds != NULL) {
429
0
          register unsigned int j = 0;
430
0
          pr_namebind_t **namebinds = NULL;
431
432
0
          namebinds = (pr_namebind_t **) ipbind->ib_namebinds->elts;
433
0
          for (j = 0; j < ipbind->ib_namebinds->nelts; j++) {
434
0
            pr_namebind_t *nb;
435
436
0
            pr_signals_handle();
437
438
0
            nb = namebinds[j];
439
0
            if (pr_namebind_close(nb->nb_name, nb->nb_server->addr) < 0) {
440
0
              pr_trace_msg(trace_channel, 7,
441
0
                "notice: error closing namebind '%s' for address %s: %s",
442
0
                nb->nb_name, pr_netaddr_get_ipstr(nb->nb_server->addr),
443
0
               strerror(errno));
444
0
            }
445
0
          }
446
0
        }
447
0
      }
448
0
    }
449
0
  }
450
451
0
  return 0;
452
0
}
453
454
/* Need a way to close all listening fds in a child process. */
455
0
int pr_ipbind_close_listeners(void) {
456
0
  conn_t **listeners;
457
0
  register unsigned int i = 0;
458
459
0
  if (listener_list == NULL ||
460
0
      listener_list->nelts == 0) {
461
0
    return 0;
462
0
  }
463
464
0
  listeners = listener_list->elts;
465
0
  for (i = 0; i < listener_list->nelts; i++) {
466
0
    conn_t *listener;
467
468
0
    pr_signals_handle();
469
470
0
    listener = listeners[i];
471
0
    if (listener->listen_fd != -1) {
472
0
      (void) close(listener->listen_fd);
473
0
      listener->listen_fd = -1;
474
0
    }
475
0
  }
476
477
0
  return 0;
478
0
}
479
480
int pr_ipbind_create(server_rec *server, const pr_netaddr_t *addr,
481
0
    unsigned int port) {
482
0
  pr_ipbind_t *existing = NULL, *ipbind = NULL;
483
0
  register unsigned int i = 0;
484
485
0
  if (server == NULL||
486
0
      addr == NULL) {
487
0
    errno = EINVAL;
488
0
    return -1;
489
0
  }
490
491
  /* Ensure the ipbind table has been initialized. */
492
0
  init_ipbind_table();
493
494
0
  i = ipbind_hash_addr(addr, port);
495
0
  pr_trace_msg(trace_channel, 29, "hashed address '%s' to index %u",
496
0
    pr_netaddr_get_ipstr(addr), i);
497
498
  /* Make sure the address is not already in use */
499
0
  for (ipbind = ipbind_table[i]; ipbind; ipbind = ipbind->ib_next) {
500
0
    pr_signals_handle();
501
502
0
    if (pr_netaddr_cmp(ipbind->ib_addr, addr) == 0 &&
503
0
        ipbind->ib_port == port) {
504
0
      existing = ipbind;
505
0
      break;
506
0
    }
507
0
  }
508
509
0
  if (existing != NULL) {
510
0
    config_rec *c;
511
512
    /* If the given server config does not have any ServerAlias directives,
513
     * then this is an IP/port collision, and we need to return an error.
514
     *
515
     * However, if there are ServerAliases, this is a name-based config and
516
     * should be processed properly.
517
     */
518
519
0
    c = find_config(server->conf, CONF_PARAM, "ServerAlias", FALSE);
520
0
    if (c == NULL) {
521
0
      pr_log_pri(PR_LOG_WARNING, "notice: '%s' (%s:%u) already bound to '%s'",
522
0
        server->ServerName, pr_netaddr_get_ipstr(addr), port,
523
0
        existing->ib_server->ServerName);
524
0
      errno = EADDRINUSE;
525
0
      return -1;
526
0
    }
527
528
0
    pr_log_debug(DEBUG9, "notice: '%s' (%s:%u) already bound to '%s'",
529
0
      server->ServerName, pr_netaddr_get_ipstr(addr), port,
530
0
      existing->ib_server->ServerName);
531
0
  }
532
533
0
  if (binding_pool == NULL) {
534
0
    binding_pool = make_sub_pool(permanent_pool);
535
0
    pr_pool_tag(binding_pool, "Bindings Pool");
536
0
  }
537
538
0
  ipbind = pcalloc(server->pool, sizeof(pr_ipbind_t));
539
0
  ipbind->ib_server = server;
540
0
  ipbind->ib_addr = addr;
541
0
  ipbind->ib_port = port;
542
0
  ipbind->ib_namebinds = NULL;
543
0
  ipbind->ib_isdefault = FALSE;
544
0
  ipbind->ib_islocalhost = FALSE;
545
0
  ipbind->ib_isactive = FALSE;
546
547
0
  pr_trace_msg(trace_channel, 8, "created ipbind %p for %s#%u, server %p (%s)",
548
0
    ipbind, pr_netaddr_get_ipstr(ipbind->ib_addr), ipbind->ib_port,
549
0
    ipbind->ib_server, ipbind->ib_server->ServerName);
550
551
  /* Add the ipbind to the table, maintaining insertion order. */
552
0
  if (existing != NULL) {
553
0
    pr_trace_msg(trace_channel, 19,
554
0
      "found existing ipbind %p (server %p) at index %u in iptable table, "
555
0
      "adding to %p", existing, existing->ib_server, i, existing);
556
0
    if (existing->ib_next != NULL) {
557
0
      ipbind->ib_next = existing->ib_next;
558
0
    }
559
0
    existing->ib_next = ipbind;
560
561
0
  } else {
562
0
    if (ipbind_table[i] != NULL) {
563
0
      ipbind->ib_next = ipbind_table[i];
564
0
    }
565
0
    ipbind_table[i] = ipbind;
566
0
  }
567
568
0
  return 0;
569
0
}
570
571
/* Returns the LAST matching ipbind for the given port, if any.  If provided,
572
 * the match_count pointer will contain the number of ipbinds found that
573
 * matched that port.
574
 */
575
static pr_ipbind_t *ipbind_find_port(unsigned int port,
576
0
    unsigned char skip_inactive, unsigned int *match_count) {
577
0
  register unsigned int i;
578
0
  pr_ipbind_t *matched_ipbind = NULL;
579
580
0
  for (i = 0; i < PR_BINDINGS_TABLE_SIZE; i++) {
581
0
    pr_ipbind_t *ipbind;
582
583
0
    for (ipbind = ipbind_table[i]; ipbind; ipbind = ipbind->ib_next) {
584
0
      pr_signals_handle();
585
586
0
      if (skip_inactive &&
587
0
          !ipbind->ib_isactive) {
588
0
        continue;
589
0
      }
590
591
0
      if (ipbind->ib_port == port) {
592
0
        if (match_count != NULL) {
593
0
          (*match_count)++;
594
0
        }
595
596
0
        matched_ipbind = ipbind;
597
0
      }
598
0
    }
599
0
  }
600
601
0
  if (matched_ipbind == NULL) {
602
0
    errno = ENOENT;
603
0
    return NULL;
604
0
  }
605
606
0
  return matched_ipbind;
607
0
}
608
609
pr_ipbind_t *pr_ipbind_find(const pr_netaddr_t *addr, unsigned int port,
610
0
    unsigned char skip_inactive) {
611
0
  register unsigned int i;
612
0
  pr_ipbind_t *ipbind = NULL;
613
614
0
  if (addr == NULL) {
615
0
    errno = EINVAL;
616
0
    return NULL;
617
0
  }
618
619
  /* Ensure the ipbind table has been initialized. */
620
0
  init_ipbind_table();
621
622
0
  i = ipbind_hash_addr(addr, port);
623
624
0
  for (ipbind = ipbind_table[i]; ipbind; ipbind = ipbind->ib_next) {
625
0
    pr_signals_handle();
626
627
0
    if (ipbind->ib_isactive == FALSE &&
628
0
        skip_inactive == TRUE) {
629
0
      continue;
630
0
    }
631
632
0
    if (pr_netaddr_cmp(ipbind->ib_addr, addr) == 0) {
633
0
      if (ipbind->ib_port == 0 ||
634
0
          port == 0 ||
635
0
          ipbind->ib_port == port) {
636
0
        return ipbind;
637
0
      }
638
0
    }
639
0
  }
640
641
0
  errno = ENOENT;
642
0
  return NULL;
643
0
}
644
645
0
pr_ipbind_t *pr_ipbind_get(pr_ipbind_t *prev) {
646
0
  static unsigned int i = 0;
647
648
0
  if (prev != NULL) {
649
    /* If there's another ipbind in this chain, simply return that. */
650
0
    if (prev->ib_next != NULL) {
651
0
      return prev->ib_next;
652
0
    }
653
654
    /* If the increment is at the maximum size, return NULL (no more chains
655
     * to be examined).
656
     */
657
0
    if (i == PR_BINDINGS_TABLE_SIZE) {
658
0
      errno = ENOENT;
659
0
      return NULL;
660
0
    }
661
662
    /* Increment the index. At this point, we know that the given pointer is
663
     * the last in the chain, and that there are more chains in the table
664
     * to be examined.
665
     */
666
0
    i++;
667
668
0
  } else {
669
    /* Reset the index if prev is NULL. */
670
0
    i = 0;
671
0
  }
672
673
  /* Search for the next non-empty chain in the table. */
674
0
  for (; i < PR_BINDINGS_TABLE_SIZE; i++) {
675
0
    pr_signals_handle();
676
677
0
    if (ipbind_table[i] != NULL) {
678
0
      return ipbind_table[i];
679
0
    }
680
0
  }
681
682
0
  errno = ENOENT;
683
0
  return NULL;
684
0
}
685
686
0
server_rec *pr_ipbind_get_server(const pr_netaddr_t *addr, unsigned int port) {
687
0
  pr_ipbind_t *ipbind = NULL;
688
0
  pr_netaddr_t wildcard_addr;
689
0
  int addr_family;
690
0
  unsigned int match_count = 0;
691
692
  /* If we've got a binding configured for this exact address, return it
693
   * straight away.
694
   */
695
0
  ipbind = pr_ipbind_find(addr, port, TRUE);
696
0
  if (ipbind != NULL) {
697
0
    pr_log_debug(DEBUG7, "matching vhost found for %s#%u, using '%s'",
698
0
      pr_netaddr_get_ipstr(addr), port, ipbind->ib_server->ServerName);
699
0
    return ipbind->ib_server;
700
0
  }
701
702
  /* Look for a vhost bound to the wildcard address (i.e. INADDR_ANY).
703
   *
704
   * This allows for "<VirtualHost 0.0.0.0>" configurations, where the
705
   * IP address to which the client might connect is not known at
706
   * configuration time.  (Usually happens when the same config file
707
   * is deployed to multiple machines.)
708
   */
709
710
0
  addr_family = pr_netaddr_get_family(addr);
711
712
0
  pr_netaddr_clear(&wildcard_addr);
713
0
  pr_netaddr_set_family(&wildcard_addr, addr_family);
714
0
  pr_netaddr_set_sockaddr_any(&wildcard_addr);
715
716
0
  ipbind = pr_ipbind_find(&wildcard_addr, port, TRUE);
717
0
  if (ipbind != NULL) {
718
0
    pr_log_debug(DEBUG7, "no matching vhost found for %s#%u, using "
719
0
      "'%s' listening on wildcard address", pr_netaddr_get_ipstr(addr), port,
720
0
      ipbind->ib_server->ServerName);
721
0
    return ipbind->ib_server;
722
0
  }
723
724
0
#ifdef PR_USE_IPV6
725
0
  if (addr_family == AF_INET6 &&
726
0
      pr_netaddr_use_ipv6()) {
727
728
    /* The pr_ipbind_find() probably returned NULL because there aren't any
729
     * <VirtualHost> sections configured explicitly for the wildcard IPv6
730
     * address of "::", just the IPv4 wildcard "0.0.0.0" address.
731
     *
732
     * So try the pr_ipbind_find() again, this time using the IPv4
733
     * wildcard.
734
     */
735
0
    pr_netaddr_clear(&wildcard_addr);
736
0
    pr_netaddr_set_family(&wildcard_addr, AF_INET);
737
0
    pr_netaddr_set_sockaddr_any(&wildcard_addr);
738
739
0
    ipbind = pr_ipbind_find(&wildcard_addr, port, TRUE);
740
0
    if (ipbind != NULL) {
741
0
      pr_log_debug(DEBUG7, "no matching vhost found for %s#%u, using "
742
0
        "'%s' listening on wildcard address", pr_netaddr_get_ipstr(addr),
743
0
        port, ipbind->ib_server->ServerName);
744
0
      return ipbind->ib_server;
745
0
    }
746
0
  }
747
0
#endif /* PR_USE_IPV6 */
748
749
  /* Check for any bindings that match the port.  IF there is only one ONE
750
   * vhost which matches the requested port, use that (Bug#4251).
751
   */
752
0
  ipbind = ipbind_find_port(port, TRUE, &match_count);
753
0
  if (ipbind != NULL) {
754
0
    pr_trace_msg(trace_channel, 18, "found %u possible %s for port %u",
755
0
      match_count, match_count != 1 ? "ipbinds" : "ipbind", port);
756
0
    if (match_count == 1) {
757
0
      return ipbind->ib_server;
758
0
    }
759
0
  }
760
761
  /* Use the default server, if set. */
762
0
  if (ipbind_default_server &&
763
0
      ipbind_default_server->ib_isactive) {
764
0
    pr_log_debug(DEBUG7, "no matching vhost found for %s#%u, using "
765
0
      "DefaultServer '%s'", pr_netaddr_get_ipstr(addr), port,
766
0
      ipbind_default_server->ib_server->ServerName);
767
0
    return ipbind_default_server->ib_server;
768
0
  }
769
770
  /* Not found in binding list, and no DefaultServer, so see if it's the
771
   * loopback address
772
   */
773
0
  if (ipbind_localhost_server &&
774
0
      pr_netaddr_is_loopback(addr)) {
775
0
    return ipbind_localhost_server->ib_server;
776
0
  }
777
778
0
  return NULL;
779
0
}
780
781
0
int pr_ipbind_listen(fd_set *readfds) {
782
0
  int listen_flags = PR_INET_LISTEN_FL_FATAL_ON_ERROR, maxfd = 0;
783
0
  register unsigned int i = 0;
784
785
  /* sanity check */
786
0
  if (readfds == NULL) {
787
0
    errno = EINVAL;
788
0
    return -1;
789
0
  }
790
791
0
  FD_ZERO(readfds);
792
793
0
  if (binding_pool == NULL) {
794
0
    binding_pool = make_sub_pool(permanent_pool);
795
0
    pr_pool_tag(binding_pool, "Bindings Pool");
796
0
  }
797
798
  /* Reset the listener list. */
799
0
  if (listener_list == NULL) {
800
0
    listener_list = make_array(binding_pool, 1, sizeof(conn_t *));
801
802
0
  } else {
803
    /* Nasty hack to "clear" the list by making it think it has no
804
     * elements.
805
     */
806
0
    listener_list->nelts = 0;
807
0
  }
808
809
  /* Slower than the hash lookup, but...we have to check each and every
810
   * ipbind in the table.
811
   */
812
0
  for (i = 0; i < PR_BINDINGS_TABLE_SIZE; i++) {
813
0
    pr_ipbind_t *ipbind = NULL;
814
815
0
    for (ipbind = ipbind_table[i]; ipbind; ipbind = ipbind->ib_next) {
816
0
      pr_signals_handle();
817
818
      /* Skip inactive bindings, but only if SocketBindTight is in effect. */
819
0
      if (SocketBindTight &&
820
0
          ipbind->ib_isactive == FALSE) {
821
0
        continue;
822
0
      }
823
824
0
      if (ipbind->ib_listener != NULL) {
825
0
        if (ipbind->ib_listener->mode == CM_NONE) {
826
0
          pr_inet_listen(ipbind->ib_listener->pool, ipbind->ib_listener,
827
0
            tcpBackLog, listen_flags);
828
0
        }
829
830
0
        if (ipbind->ib_listener->mode == CM_ACCEPT) {
831
0
          if (pr_inet_resetlisten(ipbind->ib_listener->pool,
832
0
              ipbind->ib_listener) < 0) {
833
0
            pr_trace_msg(trace_channel, 3,
834
0
              "error resetting %s#%u for listening: %s",
835
0
              pr_netaddr_get_ipstr(ipbind->ib_addr), ipbind->ib_port,
836
0
              strerror(errno));
837
0
          }
838
0
        }
839
840
0
        if (ipbind->ib_listener->mode == CM_LISTEN) {
841
0
          FD_SET(ipbind->ib_listener->listen_fd, readfds);
842
0
          if (ipbind->ib_listener->listen_fd > maxfd) {
843
0
            maxfd = ipbind->ib_listener->listen_fd;
844
0
          }
845
846
          /* Add this to the listener list as well. */
847
0
          *((conn_t **) push_array(listener_list)) = ipbind->ib_listener;
848
0
        }
849
0
      }
850
0
    }
851
0
  }
852
853
0
  return maxfd;
854
0
}
855
856
int pr_ipbind_open(const pr_netaddr_t *addr, unsigned int port,
857
    conn_t *listen_conn, unsigned char isdefault, unsigned char islocalhost,
858
0
    unsigned char open_namebinds) {
859
0
  pr_ipbind_t *ipbind = NULL;
860
861
0
  if (addr == NULL) {
862
0
    errno = EINVAL;
863
0
    return -1;
864
0
  }
865
866
  /* Find the binding for this server/address */
867
0
  ipbind = pr_ipbind_find(addr, port, FALSE);
868
0
  if (ipbind == NULL) {
869
0
    errno = ENOENT;
870
0
    return -1;
871
0
  }
872
873
0
  if (listen_conn != NULL) {
874
0
    listen_conn->next = NULL;
875
0
  }
876
877
0
  ipbind->ib_listener = ipbind->ib_server->listen = listen_conn;
878
0
  ipbind->ib_listener = listen_conn;
879
0
  ipbind->ib_isdefault = isdefault;
880
0
  ipbind->ib_islocalhost = islocalhost;
881
882
  /* Stash a pointer to this ipbind, since it is designated as the
883
   * default server (via the DefaultServer directive), for use in the
884
   * lookup functions.
885
   *
886
   * Stash pointers to this ipbind for use in the lookup functions if:
887
   *
888
   * - It's the default server (specified via the DefaultServer directive)
889
   * - It handles connections to the loopback interface
890
   */
891
0
  if (isdefault) {
892
0
    ipbind_default_server = ipbind;
893
0
  }
894
895
0
  if (islocalhost) {
896
0
    ipbind_localhost_server = ipbind;
897
0
  }
898
899
  /* If requested, look for any namebinds for this ipbind, and open them. */
900
0
  if (open_namebinds &&
901
0
      ipbind->ib_namebinds) {
902
0
    register unsigned int i = 0;
903
0
    pr_namebind_t **namebinds = NULL;
904
905
    /* NOTE: in the future, these namebinds may need to be stored/
906
     * manipulated in hash tables themselves, but, for now, linked lists
907
     * should suffice.
908
     */
909
0
    namebinds = (pr_namebind_t **) ipbind->ib_namebinds->elts;
910
0
    for (i = 0; i < ipbind->ib_namebinds->nelts; i++) {
911
0
      int res;
912
0
      pr_namebind_t *nb;
913
914
0
      pr_signals_handle();
915
916
0
      nb = namebinds[i];
917
0
      res = pr_namebind_open(nb->nb_name, nb->nb_server->addr,
918
0
        nb->nb_server_port);
919
0
      if (res < 0) {
920
0
        pr_trace_msg(trace_channel, 2,
921
0
          "notice: unable to open namebind '%s': %s", nb->nb_name,
922
0
          strerror(errno));
923
0
      }
924
0
    }
925
0
  }
926
927
  /* Mark this binding as now being active. */
928
0
  ipbind->ib_isactive = TRUE;
929
930
0
  return 0;
931
0
}
932
933
0
int pr_namebind_close(const char *name, const pr_netaddr_t *addr) {
934
0
  pr_namebind_t *namebind = NULL;
935
0
  unsigned int port;
936
937
0
  if (name == NULL||
938
0
      addr == NULL) {
939
0
    errno = EINVAL;
940
0
    return -1;
941
0
  }
942
943
0
  port = ntohs(pr_netaddr_get_port(addr));
944
0
  namebind = pr_namebind_find(name, addr, port, FALSE);
945
0
  if (namebind == NULL) {
946
0
    errno = ENOENT;
947
0
    return -1;
948
0
  }
949
950
0
  namebind->nb_isactive = FALSE;
951
0
  return 0;
952
0
}
953
954
int pr_namebind_create(server_rec *server, const char *name,
955
0
    pr_ipbind_t *ipbind, const pr_netaddr_t *addr, unsigned int server_port) {
956
0
  pr_namebind_t *namebind = NULL, **namebinds = NULL;
957
0
  unsigned int port;
958
959
0
  if (server == NULL ||
960
0
      name == NULL) {
961
0
    errno = EINVAL;
962
0
    return -1;
963
0
  }
964
965
  /* First, find the ipbind to hold this namebind. */
966
0
  port = ntohs(pr_netaddr_get_port(addr));
967
0
  if (port == 0) {
968
0
    port = server_port;
969
0
  }
970
971
0
  if (ipbind == NULL) {
972
0
    pr_netaddr_t wildcard_addr;
973
0
    int addr_family;
974
975
    /* If not found, look for the wildcard address. */
976
977
0
    addr_family = pr_netaddr_get_family(addr);
978
0
    pr_netaddr_clear(&wildcard_addr);
979
0
    pr_netaddr_set_family(&wildcard_addr, addr_family);
980
0
    pr_netaddr_set_sockaddr_any(&wildcard_addr);
981
982
0
    ipbind = pr_ipbind_find(&wildcard_addr, port, FALSE);
983
0
#ifdef PR_USE_IPV6
984
0
    if (ipbind == FALSE &&
985
0
        addr_family == AF_INET6 &&
986
0
        pr_netaddr_use_ipv6()) {
987
988
      /* No IPv6 wildcard address found; try the IPv4 wildcard address. */
989
0
      pr_netaddr_clear(&wildcard_addr);
990
0
      pr_netaddr_set_family(&wildcard_addr, AF_INET);
991
0
      pr_netaddr_set_sockaddr_any(&wildcard_addr);
992
993
0
      ipbind = pr_ipbind_find(&wildcard_addr, port, FALSE);
994
0
    }
995
0
#endif /* PR_USE_IPV6 */
996
997
0
    pr_trace_msg(trace_channel, 19,
998
0
      "found wildcard ipbind %p for namebind (name '%s', addr %s, port %u)",
999
0
      ipbind, name, pr_netaddr_get_ipstr(addr), port);
1000
0
  }
1001
1002
0
  if (ipbind == NULL) {
1003
0
    errno = ENOENT;
1004
0
    return -1;
1005
0
  }
1006
1007
  /* Make sure we can add this namebind. */
1008
0
  if (ipbind->ib_namebinds == NULL) {
1009
0
    ipbind->ib_namebinds = make_array(binding_pool, 0, sizeof(pr_namebind_t *));
1010
1011
0
  } else {
1012
0
    register unsigned int i = 0;
1013
0
    namebinds = (pr_namebind_t **) ipbind->ib_namebinds->elts;
1014
1015
    /* See if there is already a namebind for the given name. */
1016
0
    for (i = 0; i < ipbind->ib_namebinds->nelts; i++) {
1017
0
      pr_signals_handle();
1018
1019
0
      namebind = namebinds[i];
1020
0
      if (namebind != NULL &&
1021
0
          namebind->nb_name != NULL) {
1022
1023
        /* DNS names are case-insensitive, hence the case-insensitive check
1024
         * here.
1025
         *
1026
         * XXX Ideally, we should check whether any existing namebinds which
1027
         * are globs will match the newly added namebind as well.
1028
         */
1029
1030
0
        if (strcasecmp(namebind->nb_name, name) == 0) {
1031
0
          errno = EEXIST;
1032
0
          return -1;
1033
0
        }
1034
0
      }
1035
0
    }
1036
0
  }
1037
1038
0
  namebind = (pr_namebind_t *) pcalloc(server->pool, sizeof(pr_namebind_t));
1039
0
  namebind->nb_name = name;
1040
0
  namebind->nb_server = server;
1041
0
  namebind->nb_server_port = server_port;
1042
0
  namebind->nb_isactive = FALSE;
1043
1044
0
  if (pr_str_is_fnmatch(name) == TRUE) {
1045
0
    namebind->nb_iswildcard = TRUE;
1046
0
  }
1047
1048
0
  pr_trace_msg(trace_channel, 8,
1049
0
    "created namebind '%s' for %s#%u, server '%s' [%p]", name,
1050
0
    pr_netaddr_get_ipstr(server->addr), server->ServerPort, server->ServerName,
1051
0
    server);
1052
1053
  /* The given server should already have the following populated:
1054
   *
1055
   *  server->ServerName
1056
   *  server->ServerAddress
1057
   *  server->ServerFQDN
1058
   */
1059
1060
0
  *((pr_namebind_t **) push_array(ipbind->ib_namebinds)) = namebind;
1061
0
  return 0;
1062
0
}
1063
1064
pr_namebind_t *pr_namebind_find(const char *name, const pr_netaddr_t *addr,
1065
0
    unsigned int port, unsigned char skip_inactive) {
1066
0
  pr_ipbind_t *ipbind = NULL, *iter;
1067
1068
0
  if (name == NULL ||
1069
0
      addr == NULL) {
1070
0
    errno = EINVAL;
1071
0
    return NULL;
1072
0
  }
1073
1074
  /* First, find an active ipbind for the given address. */
1075
0
  ipbind = pr_ipbind_find(addr, port, skip_inactive);
1076
0
  if (ipbind == NULL) {
1077
0
    pr_netaddr_t wildcard_addr;
1078
0
    int addr_family;
1079
1080
    /* If not found, look for the wildcard address. */
1081
1082
0
    addr_family = pr_netaddr_get_family(addr);
1083
0
    pr_netaddr_clear(&wildcard_addr);
1084
0
    pr_netaddr_set_family(&wildcard_addr, addr_family);
1085
0
    pr_netaddr_set_sockaddr_any(&wildcard_addr);
1086
1087
0
    ipbind = pr_ipbind_find(&wildcard_addr, port, FALSE);
1088
0
#ifdef PR_USE_IPV6
1089
0
    if (ipbind == FALSE &&
1090
0
        addr_family == AF_INET6 &&
1091
0
        pr_netaddr_use_ipv6()) {
1092
1093
      /* No IPv6 wildcard address found; try the IPv4 wildcard address. */
1094
0
      pr_netaddr_clear(&wildcard_addr);
1095
0
      pr_netaddr_set_family(&wildcard_addr, AF_INET);
1096
0
      pr_netaddr_set_sockaddr_any(&wildcard_addr);
1097
1098
0
      ipbind = pr_ipbind_find(&wildcard_addr, port, FALSE);
1099
0
    }
1100
0
#endif /* PR_USE_IPV6 */
1101
0
  } else {
1102
0
    pr_trace_msg(trace_channel, 17,
1103
0
      "found ipbind %p (server '%s' [%p]) for %s#%u", ipbind,
1104
0
      ipbind->ib_server->ServerName, ipbind->ib_server,
1105
0
      pr_netaddr_get_ipstr(addr), port);
1106
0
  }
1107
1108
0
  if (ipbind == NULL) {
1109
0
    errno = ENOENT;
1110
0
    return NULL;
1111
0
  }
1112
1113
  /* Now we need to search this ipbind list, to see if any of them have a
1114
   * matching namebind.
1115
   */
1116
1117
0
  for (iter = ipbind; iter; iter = iter->ib_next) {
1118
0
    register unsigned int i = 0;
1119
0
    pr_namebind_t *namebind = NULL, **namebinds = NULL;
1120
1121
0
    pr_signals_handle();
1122
1123
0
    if (iter->ib_namebinds == NULL) {
1124
0
      pr_trace_msg(trace_channel, 17,
1125
0
        "ipbind %p (server %p) for %s#%u has no namebinds", iter,
1126
0
        iter->ib_server, pr_netaddr_get_ipstr(addr), port);
1127
0
      continue;
1128
0
    }
1129
1130
0
    namebinds = (pr_namebind_t **) iter->ib_namebinds->elts;
1131
0
    pr_trace_msg(trace_channel, 17,
1132
0
      "ipbind %p (server %p) for %s#%u has namebinds (%d)", iter,
1133
0
      iter->ib_server, pr_netaddr_get_ipstr(addr), port,
1134
0
      iter->ib_namebinds->nelts);
1135
1136
0
    for (i = 0; i < iter->ib_namebinds->nelts; i++) {
1137
0
      pr_signals_handle();
1138
1139
0
      namebind = namebinds[i];
1140
0
      if (namebind == NULL) {
1141
0
        continue;
1142
0
      }
1143
1144
      /* Skip inactive namebinds */
1145
0
      if (skip_inactive == TRUE &&
1146
0
          namebind->nb_isactive == FALSE) {
1147
0
        pr_trace_msg(trace_channel, 17,
1148
0
          "namebind #%u: %s is inactive, skipping", i, namebind->nb_name);
1149
0
        continue;
1150
0
      }
1151
1152
      /* At present, this looks for an exactly matching name.  In the future,
1153
       * we may want to have something like Apache's matching scheme, which
1154
       * looks for the most specific domain to the most general.  Note that
1155
       * that scheme, however, is specific to DNS; should any other naming
1156
       * scheme be desired, that sort of matching will be unnecessary.
1157
       */
1158
0
      if (namebind->nb_name != NULL) {
1159
0
        pr_trace_msg(trace_channel, 17,
1160
0
          "namebind #%u: %s (%s)", i, namebind->nb_name,
1161
0
          namebind->nb_isactive ? "active" : "inactive");
1162
1163
0
        if (namebind->nb_iswildcard == FALSE) {
1164
0
          if (strcasecmp(namebind->nb_name, name) == 0) {
1165
0
            return namebind;
1166
0
          }
1167
1168
0
        } else {
1169
0
          int match_flags = PR_FNM_NOESCAPE|PR_FNM_CASEFOLD;
1170
1171
0
          if (pr_fnmatch(namebind->nb_name, name, match_flags) == 0) {
1172
0
            pr_trace_msg(trace_channel, 9,
1173
0
              "matched name '%s' against pattern '%s'", name,
1174
0
              namebind->nb_name);
1175
0
            return namebind;
1176
0
          }
1177
1178
0
          pr_trace_msg(trace_channel, 9,
1179
0
            "failed to match name '%s' against pattern '%s'", name,
1180
0
            namebind->nb_name);
1181
0
        }
1182
0
      }
1183
0
    }
1184
0
  }
1185
1186
0
  return NULL;
1187
0
}
1188
1189
server_rec *pr_namebind_get_server(const char *name, const pr_netaddr_t *addr,
1190
0
    unsigned int port) {
1191
0
  pr_namebind_t *namebind = NULL;
1192
1193
  /* Basically, just a wrapper around pr_namebind_find() */
1194
1195
0
  namebind = pr_namebind_find(name, addr, port, TRUE);
1196
0
  if (namebind == NULL) {
1197
0
    return NULL;
1198
0
  }
1199
1200
0
  return namebind->nb_server;
1201
0
}
1202
1203
0
unsigned int pr_namebind_count(server_rec *srv) {
1204
0
  unsigned int count = 0;
1205
0
  pr_ipbind_t *ipbind = NULL;
1206
1207
0
  if (srv == NULL) {
1208
0
    return 0;
1209
0
  }
1210
1211
0
  ipbind = pr_ipbind_find(srv->addr, srv->ServerPort, FALSE);
1212
0
  if (ipbind != NULL &&
1213
0
      ipbind->ib_namebinds != NULL) {
1214
0
    count = ipbind->ib_namebinds->nelts;
1215
0
  }
1216
1217
0
  return count;
1218
0
}
1219
1220
int pr_namebind_open(const char *name, const pr_netaddr_t *addr,
1221
0
    unsigned int server_port) {
1222
0
  pr_namebind_t *namebind = NULL;
1223
0
  unsigned int port;
1224
1225
0
  if (name == NULL ||
1226
0
      addr == NULL) {
1227
0
    errno = EINVAL;
1228
0
    return -1;
1229
0
  }
1230
1231
0
  port = ntohs(pr_netaddr_get_port(addr));
1232
0
  if (port == 0) {
1233
0
    port = server_port;
1234
0
  }
1235
1236
0
  namebind = pr_namebind_find(name, addr, port, FALSE);
1237
0
  if (namebind == NULL) {
1238
0
    errno = ENOENT;
1239
0
    return -1;
1240
0
  }
1241
1242
0
  namebind->nb_isactive = TRUE;
1243
0
  return 0;
1244
0
}
1245
1246
0
void free_bindings(void) {
1247
0
  if (binding_pool) {
1248
0
    destroy_pool(binding_pool);
1249
0
    binding_pool = NULL;
1250
0
    listener_list = NULL;
1251
0
  }
1252
1253
0
  memset(ipbind_table, 0, sizeof(ipbind_table));
1254
0
  ipbind_table_initialized = FALSE;
1255
1256
  /* Mark all listening conns as "unclaimed"; any that remaining unclaimed
1257
   * after init_bindings() can be closed.
1258
   */
1259
0
  if (listening_conn_list != NULL) {
1260
0
    struct listener_rec *lr;
1261
1262
0
    for (lr = (struct listener_rec *) listening_conn_list->xas_list; lr; lr = lr->next) {
1263
0
      pr_signals_handle();
1264
0
      lr->claimed = FALSE;
1265
0
    }
1266
0
  }
1267
0
}
1268
1269
0
static int init_inetd_bindings(void) {
1270
0
  int res = 0;
1271
0
  server_rec *serv = NULL;
1272
0
  unsigned char *default_server = NULL, is_default = FALSE;
1273
1274
  /* We explicitly do NOT use the get_listening_conn() function here, since
1275
   * inetd-run daemons will not a) handle restarts, and thus b) will not have
1276
   * already-open connections to choose from.
1277
   */
1278
1279
0
  main_server->listen = pr_inet_create_conn(main_server->pool, STDIN_FILENO,
1280
0
    NULL, INPORT_ANY, FALSE);
1281
0
  if (main_server->listen == NULL) {
1282
0
    return -1;
1283
0
  }
1284
1285
  /* Note: Since we are being called via inetd/xinetd, any socket options
1286
   * which may be attempted by listeners for this event may not work.
1287
   */
1288
0
  pr_inet_generate_socket_event("core.ctrl-listen", main_server,
1289
0
    main_server->addr, main_server->listen->listen_fd);
1290
1291
  /* Fill in all the important connection information. */
1292
0
  if (pr_inet_get_conn_info(main_server->listen, STDIN_FILENO) == -1) {
1293
0
    int xerrno = errno;
1294
1295
0
    pr_log_pri(PR_LOG_WARNING, "fatal: unable to get connection info: %s",
1296
0
      strerror(xerrno));
1297
1298
0
    if (xerrno == ENOTSOCK) {
1299
0
      pr_log_pri(PR_LOG_ERR, "(Running from command line? "
1300
0
        "Use `ServerType standalone' in config file!)");
1301
0
    }
1302
1303
0
    exit(1);
1304
0
  }
1305
1306
0
  default_server = get_param_ptr(main_server->conf, "DefaultServer", FALSE);
1307
0
  if (default_server != NULL &&
1308
0
      *default_server == TRUE) {
1309
0
    is_default = TRUE;
1310
0
  }
1311
1312
0
  res = pr_ipbind_create(main_server, main_server->addr,
1313
0
    main_server->ServerPort);
1314
0
  if (res < 0) {
1315
0
    pr_log_pri(PR_LOG_NOTICE,
1316
0
      "%s:%d: notice: unable to create ipbind '%s#%u': %s", __FILE__, __LINE__,
1317
0
      main_server->ServerAddress, main_server->ServerPort, strerror(errno));
1318
0
  }
1319
1320
0
  res = pr_ipbind_open(main_server->addr, main_server->ServerPort,
1321
0
    main_server->listen, is_default, TRUE, TRUE);
1322
0
  if (res < 0) {
1323
0
    pr_log_pri(PR_LOG_NOTICE,
1324
0
      "%s:%d: notice: unable to open ipbind '%s': %s", __FILE__, __LINE__,
1325
0
      pr_netaddr_get_ipstr(main_server->addr), strerror(errno));
1326
0
  }
1327
1328
0
  res = pr_ipbind_add_binds(main_server);
1329
0
  if (res < 0) {
1330
0
    pr_log_pri(PR_LOG_NOTICE,
1331
0
      "%s:%d: notice: unable to add binds to ipbind '%s': %s", __FILE__,
1332
0
      __LINE__, main_server->ServerAddress, strerror(errno));
1333
0
  }
1334
1335
  /* Now attach the faked connection to all virtual servers. */
1336
0
  for (serv = main_server->next; serv; serv = serv->next) {
1337
1338
    /* Because this server is sharing the connection with the
1339
     * main server, we need a cleanup handler to remove
1340
     * the server's reference when the original connection's
1341
     * pool is destroyed.
1342
     */
1343
1344
0
    serv->listen = main_server->listen;
1345
0
    register_cleanup2(serv->listen->pool, &serv->listen, server_cleanup_cb);
1346
1347
0
    is_default = FALSE;
1348
0
    default_server = get_param_ptr(serv->conf, "DefaultServer", FALSE);
1349
0
    if (default_server != NULL &&
1350
0
        *default_server == TRUE) {
1351
0
      is_default = TRUE;
1352
0
    }
1353
1354
0
    res = pr_ipbind_create(serv, serv->addr, serv->ServerPort);
1355
0
    if (res < 0) {
1356
0
      pr_log_pri(PR_LOG_NOTICE,
1357
0
        "%s:%d: notice: unable to create ipbind '%s#%u': %s", __FILE__,
1358
0
        __LINE__, serv->ServerAddress, serv->ServerPort, strerror(errno));
1359
0
    }
1360
1361
0
    res = pr_ipbind_open(serv->addr, serv->ServerPort, serv->listen,
1362
0
      is_default, FALSE, TRUE);
1363
0
    if (res < 0) {
1364
0
      pr_log_pri(PR_LOG_NOTICE,
1365
0
        "%s:%d: notice: unable to open ipbind '%s': %s", __FILE__, __LINE__,
1366
0
        pr_netaddr_get_ipstr(serv->addr), strerror(errno));
1367
0
    }
1368
1369
0
    res = pr_ipbind_add_binds(serv);
1370
0
    if (res < 0) {
1371
0
      pr_log_pri(PR_LOG_NOTICE,
1372
0
        "%s:%d: notice: unable to add binds to ipbind '%s': %s", __FILE__,
1373
0
        __LINE__, serv->ServerAddress, strerror(errno));
1374
0
    }
1375
0
  }
1376
1377
0
  return 0;
1378
0
}
1379
1380
0
static array_header *find_server_ipbinds(pool *p, server_rec *s) {
1381
0
  register unsigned int i;
1382
0
  array_header *ipbinds = NULL;
1383
1384
0
  for (i = 0; i < PR_BINDINGS_TABLE_SIZE; i++) {
1385
0
    pr_ipbind_t *ipbind;
1386
1387
0
    for (ipbind = ipbind_table[i]; ipbind != NULL; ipbind = ipbind->ib_next) {
1388
0
      pr_signals_handle();
1389
1390
0
      if (ipbind->ib_server == s) {
1391
0
        if (ipbinds == NULL) {
1392
0
          ipbinds = make_array(p, 16, sizeof(pr_ipbind_t *));
1393
0
        }
1394
1395
0
        *((pr_ipbind_t **) push_array(ipbinds)) = ipbind;
1396
0
      }
1397
0
    }
1398
0
  }
1399
1400
0
  return ipbinds;
1401
0
}
1402
1403
0
static unsigned int process_serveralias(server_rec *s) {
1404
0
  unsigned namebind_count = 0;
1405
0
  config_rec *c;
1406
0
  pr_ipbind_t *ipbind;
1407
0
  array_header *ipbinds;
1408
0
  pool *tmp_pool;
1409
1410
  /* If there is no ipbind already for this server, we cannot associate
1411
   * any ServerAlias-based namebinds to it.
1412
   *
1413
   * Keep in mind that there may be multiple ipbinds pointed at this server:
1414
   *
1415
   *  <VirtualHost 1.2.3.4 5.6.7.8>
1416
   *    ServerAlias alias
1417
   *  </VirtualHost>
1418
   *
1419
   * And that multiple namebinds can point to the same ipbind for this server:
1420
   *
1421
   *  <VirtualHost 1.2.3.4>
1422
   *    ServerAlias first
1423
   *  </VirtualHost>
1424
   *
1425
   *  <VirtualHost 2.3.4.5>
1426
   *    ServerAlias second
1427
   *  </VirtualHost>
1428
   */
1429
1430
0
  tmp_pool = make_sub_pool(s->pool);
1431
0
  pr_pool_tag(tmp_pool, "ServerAlias Processing Pool");
1432
1433
  /* Remember that this will return cases where port is zero, too. */
1434
0
  ipbind = pr_ipbind_find(s->addr, s->ServerPort, FALSE);
1435
0
  if (ipbind != NULL &&
1436
0
      ipbind->ib_server->ServerPort == s->ServerPort) {
1437
0
    ipbinds = make_array(tmp_pool, 1, sizeof(pr_ipbind_t *));
1438
0
    *((pr_ipbind_t **) push_array(ipbinds)) = ipbind;
1439
1440
0
  } else {
1441
0
    ipbinds = find_server_ipbinds(tmp_pool, s);
1442
0
    if (ipbinds == NULL) {
1443
0
      destroy_pool(tmp_pool);
1444
0
      return 0;
1445
0
    }
1446
0
  }
1447
1448
0
  c = find_config(s->conf, CONF_PARAM, "ServerAlias", FALSE);
1449
0
  while (c != NULL) {
1450
0
    register unsigned int i;
1451
0
    int res;
1452
0
    pr_ipbind_t **elts;
1453
1454
0
    pr_signals_handle();
1455
1456
0
    pr_trace_msg(trace_channel, 7, "handling ipbinds (%d) for ServerAlias '%s'",
1457
0
      ipbinds->nelts, (char *) c->argv[0]);
1458
1459
0
    elts = ipbinds->elts;
1460
0
    for (i = 0; i < ipbinds->nelts; i++) {
1461
0
      pr_signals_handle();
1462
1463
0
      ipbind = elts[i];
1464
0
      pr_trace_msg(trace_channel, 7, "adding ServerAlias '%s' to server '%s'",
1465
0
        (char *) c->argv[0], s->ServerName);
1466
1467
0
      res = pr_namebind_create(s, c->argv[0], ipbind, s->addr, s->ServerPort);
1468
0
      if (res == 0) {
1469
0
        namebind_count++;
1470
1471
0
        res = pr_namebind_open(c->argv[0], ipbind->ib_addr, ipbind->ib_port);
1472
0
        if (res < 0) {
1473
0
          pr_trace_msg(trace_channel, 2,
1474
0
            "notice: unable to open namebind '%s': %s", (char *) c->argv[0],
1475
0
            strerror(errno));
1476
0
        }
1477
1478
0
      } else {
1479
0
        if (errno != ENOENT) {
1480
0
          pr_trace_msg(trace_channel, 3,
1481
0
            "unable to create namebind for '%s' to %s#%u: %s",
1482
0
            (char *) c->argv[0], pr_netaddr_get_ipstr(ipbind->ib_addr),
1483
0
            ipbind->ib_port, strerror(errno));
1484
0
        }
1485
0
      }
1486
0
    }
1487
1488
0
    c = find_config_next(c, c->next, CONF_PARAM, "ServerAlias", FALSE);
1489
0
  }
1490
1491
0
  destroy_pool(tmp_pool);
1492
0
  return namebind_count;
1493
0
}
1494
1495
0
static void trace_ipbind_table(void) {
1496
0
  register unsigned int i;
1497
1498
0
  if (pr_trace_get_level(trace_channel) < 25) {
1499
0
    return;
1500
0
  }
1501
1502
0
  pr_trace_msg(trace_channel, 25, "displaying ipbind table:");
1503
0
  for (i = 0; i < PR_BINDINGS_TABLE_SIZE; i++) {
1504
0
    pr_ipbind_t *ipbind;
1505
1506
0
    pr_signals_handle();
1507
1508
0
    if (ipbind_table[i] == NULL) {
1509
0
      continue;
1510
0
    }
1511
1512
0
    pr_trace_msg(trace_channel, 25, "  index %u:", i);
1513
0
    for (ipbind = ipbind_table[i]; ipbind; ipbind = ipbind->ib_next) {
1514
0
      array_header *namebinds;
1515
1516
0
      pr_signals_handle();
1517
0
      namebinds = ipbind->ib_namebinds;
1518
1519
0
      pr_trace_msg(trace_channel, 25, "    ipbind %p:", ipbind);
1520
0
      pr_trace_msg(trace_channel, 25, "      address: %s#%u",
1521
0
        pr_netaddr_get_ipstr(ipbind->ib_addr), ipbind->ib_port);
1522
0
      pr_trace_msg(trace_channel, 25, "      server: %s (%p)",
1523
0
        ipbind->ib_server->ServerName, ipbind->ib_server);
1524
0
      pr_trace_msg(trace_channel, 25, "      active: %s",
1525
0
        ipbind->ib_isactive ? "TRUE" : "FALSE");
1526
1527
0
      if (namebinds != NULL) {
1528
0
        register unsigned int k;
1529
0
        pr_namebind_t **elts;
1530
1531
0
        pr_trace_msg(trace_channel, 25, "      namebinds:");
1532
0
        elts = namebinds->elts;
1533
0
        for (k = 0; k < namebinds->nelts; k++) {
1534
0
          pr_namebind_t *namebind;
1535
1536
0
          pr_signals_handle();
1537
0
          namebind = elts[k];
1538
0
          pr_trace_msg(trace_channel, 25, "      #%u: %p", k+1, namebind);
1539
0
          pr_trace_msg(trace_channel, 25, "        name: %s",
1540
0
            namebind->nb_server->ServerName);
1541
0
          pr_trace_msg(trace_channel, 25, "        alias: %s",
1542
0
            namebind->nb_name);
1543
0
          pr_trace_msg(trace_channel, 25, "        server: %p",
1544
0
            namebind->nb_server);
1545
0
          pr_trace_msg(trace_channel, 25, "        active: %s",
1546
0
            namebind->nb_isactive ? "TRUE" : "FALSE");
1547
0
        }
1548
0
      }
1549
0
    }
1550
0
  }
1551
0
}
1552
1553
0
static int init_standalone_bindings(void) {
1554
0
  int res = 0;
1555
0
  server_rec *serv = NULL;
1556
0
  unsigned char *default_server = NULL, is_default = FALSE;
1557
1558
  /* Ensure the ipbind table has been initialized. */
1559
0
  init_ipbind_table();
1560
1561
  /* If a port is set to zero, the address/port is not bound to a socket
1562
   * at all.
1563
   */
1564
0
  if (main_server->ServerPort > 0) {
1565
    /* If SocketBindTight is off, then pr_inet_create_conn() will
1566
     * create and bind to a wildcard socket.  However, should it be an
1567
     * IPv4 or an IPv6 wildcard socket?
1568
     */
1569
0
    if (!SocketBindTight) {
1570
0
#if defined(PR_USE_IPV6)
1571
0
      if (pr_netaddr_use_ipv6()) {
1572
0
        pr_inet_set_default_family(NULL, AF_INET6);
1573
1574
0
      } else {
1575
0
        int default_family;
1576
1577
0
        default_family = pr_netaddr_get_family(main_server->addr);
1578
0
        pr_inet_set_default_family(NULL, default_family);
1579
0
      }
1580
#else
1581
      pr_inet_set_default_family(NULL,
1582
        pr_netaddr_get_family(main_server->addr));
1583
#endif /* PR_USE_IPV6 */
1584
0
    }
1585
1586
0
    main_server->listen = pr_ipbind_get_listening_conn(main_server,
1587
0
      (SocketBindTight ? main_server->addr : NULL), main_server->ServerPort);
1588
0
    if (main_server->listen == NULL) {
1589
0
      return -1;
1590
0
    }
1591
1592
0
  } else {
1593
0
    main_server->listen = NULL;
1594
0
  }
1595
1596
0
  default_server = get_param_ptr(main_server->conf, "DefaultServer", FALSE);
1597
0
  if (default_server != NULL &&
1598
0
      *default_server == TRUE) {
1599
0
    is_default = TRUE;
1600
0
  }
1601
1602
0
  if (main_server->ServerPort == 0) {
1603
    /* If there is no server port, then this vhost cannot be treated as the
1604
     * DefaultServer.
1605
     */
1606
0
    is_default = FALSE;
1607
0
  }
1608
1609
0
  if (main_server->ServerPort > 0 ||
1610
0
      is_default == TRUE) {
1611
1612
0
    res = pr_ipbind_create(main_server, main_server->addr,
1613
0
      main_server->ServerPort);
1614
0
    if (res < 0) {
1615
0
      pr_log_pri(PR_LOG_NOTICE,
1616
0
        "%s:%d: notice: unable to create ipbind '%s#%u': %s", __FILE__,
1617
0
        __LINE__, main_server->ServerAddress, main_server->ServerPort,
1618
0
        strerror(errno));
1619
0
    }
1620
1621
0
    res = pr_ipbind_open(main_server->addr, main_server->ServerPort,
1622
0
      main_server->listen, is_default, TRUE, TRUE);
1623
0
    if (res < 0) {
1624
0
      pr_log_pri(PR_LOG_NOTICE,
1625
0
        "%s:%d: notice: unable to open ipbind '%s': %s", __FILE__, __LINE__,
1626
0
        pr_netaddr_get_ipstr(main_server->addr), strerror(errno));
1627
0
    }
1628
1629
0
    res = pr_ipbind_add_binds(main_server);
1630
0
    if (res < 0) {
1631
0
      pr_log_pri(PR_LOG_NOTICE,
1632
0
        "%s:%d: notice: unable to add binds to ipbind '%s': %s", __FILE__,
1633
0
        __LINE__, main_server->ServerAddress, strerror(errno));
1634
0
    }
1635
0
  }
1636
1637
0
  for (serv = main_server->next; serv; serv = serv->next) {
1638
0
    unsigned int namebind_count;
1639
1640
0
    pr_signals_handle();
1641
1642
0
    namebind_count = process_serveralias(serv);
1643
0
    if (namebind_count > 0) {
1644
      /* If we successfully added ServerAlias namebinds, move on to the next
1645
       * server.
1646
       */
1647
0
      continue;
1648
0
    }
1649
1650
0
    if (serv->ServerPort != main_server->ServerPort ||
1651
0
        SocketBindTight ||
1652
0
        !main_server->listen) {
1653
0
      is_default = FALSE;
1654
1655
0
      default_server = get_param_ptr(serv->conf, "DefaultServer", FALSE);
1656
0
      if (default_server != NULL &&
1657
0
          *default_server == TRUE) {
1658
0
        is_default = TRUE;
1659
0
      }
1660
1661
0
      if (serv->ServerPort == 0) {
1662
        /* If there is no server port, then this vhost cannot be treated as the
1663
         * DefaultServer.
1664
         */
1665
0
        is_default = FALSE;
1666
0
      }
1667
1668
0
      if (serv->ServerPort > 0) {
1669
0
        if (SocketBindTight == FALSE) {
1670
0
#ifdef PR_USE_IPV6
1671
0
          if (pr_netaddr_use_ipv6()) {
1672
0
            pr_inet_set_default_family(NULL, AF_INET6);
1673
1674
0
          } else {
1675
0
            pr_inet_set_default_family(NULL, pr_netaddr_get_family(serv->addr));
1676
0
          }
1677
#else
1678
          pr_inet_set_default_family(NULL, pr_netaddr_get_family(serv->addr));
1679
#endif /* PR_USE_IPV6 */
1680
0
        }
1681
1682
0
        serv->listen = pr_ipbind_get_listening_conn(serv,
1683
0
          (SocketBindTight ? serv->addr : NULL), serv->ServerPort);
1684
0
        if (serv->listen == NULL) {
1685
0
          return -1;
1686
0
        }
1687
1688
0
        res = pr_ipbind_create(serv, serv->addr, serv->ServerPort);
1689
0
        if (res < 0) {
1690
0
          pr_log_pri(PR_LOG_NOTICE,
1691
0
            "%s:%d: notice: unable to create ipbind '%s#%u': %s", __FILE__,
1692
0
            __LINE__, serv->ServerAddress, serv->ServerPort, strerror(errno));
1693
0
        }
1694
1695
0
        res = pr_ipbind_open(serv->addr, serv->ServerPort, serv->listen,
1696
0
          is_default, FALSE, TRUE);
1697
0
        if (res < 0) {
1698
0
          pr_log_pri(PR_LOG_NOTICE,
1699
0
            "%s:%d: notice: unable to open ipbind '%s': %s", __FILE__, __LINE__,
1700
0
            pr_netaddr_get_ipstr(serv->addr), strerror(errno));
1701
0
        }
1702
1703
0
        res = pr_ipbind_add_binds(serv);
1704
0
        if (res < 0) {
1705
0
          pr_log_pri(PR_LOG_NOTICE,
1706
0
            "%s:%d: notice: unable to add binds to ipbind '%s': %s", __FILE__,
1707
0
            __LINE__, serv->ServerAddress, strerror(errno));
1708
0
        }
1709
1710
0
      } else if (is_default == TRUE) {
1711
0
        serv->listen = NULL;
1712
1713
0
        res = pr_ipbind_create(serv, serv->addr, serv->ServerPort);
1714
0
        if (res < 0) {
1715
0
          pr_log_pri(PR_LOG_NOTICE,
1716
0
            "%s:%d: notice: unable to create ipbind '%s#%u': %s", __FILE__,
1717
0
            __LINE__, serv->ServerAddress, serv->ServerPort, strerror(errno));
1718
0
        }
1719
1720
0
        res = pr_ipbind_open(serv->addr, serv->ServerPort, serv->listen,
1721
0
          is_default, FALSE, TRUE);
1722
0
        if (res < 0) {
1723
0
          pr_log_pri(PR_LOG_NOTICE,
1724
0
            "%s:%d: notice: unable to open ipbind '%s': %s", __FILE__, __LINE__,
1725
0
            pr_netaddr_get_ipstr(serv->addr), strerror(errno));
1726
0
        }
1727
1728
0
        res = pr_ipbind_add_binds(serv);
1729
0
        if (res < 0) {
1730
0
          pr_log_pri(PR_LOG_NOTICE,
1731
0
            "%s:%d: notice: unable to add binds to ipbind '%s': %s", __FILE__,
1732
0
            __LINE__, serv->ServerAddress, strerror(errno));
1733
0
        }
1734
1735
0
      } else {
1736
0
        serv->listen = NULL;
1737
0
      }
1738
1739
0
    } else {
1740
      /* Because this server is sharing the connection with the main server,
1741
       * we need a cleanup handler to remove the server's reference when the
1742
       * original connection's pool is destroyed.
1743
       */
1744
1745
0
      is_default = FALSE;
1746
0
      default_server = get_param_ptr(serv->conf, "DefaultServer", FALSE);
1747
0
      if (default_server != NULL &&
1748
0
          *default_server == TRUE) {
1749
0
        is_default = TRUE;
1750
0
      }
1751
1752
0
      serv->listen = main_server->listen;
1753
0
      register_cleanup2(serv->listen->pool, &serv->listen, server_cleanup_cb);
1754
1755
0
      res = pr_ipbind_create(serv, serv->addr, serv->ServerPort);
1756
0
      if (res < 0) {
1757
0
        pr_log_pri(PR_LOG_NOTICE,
1758
0
          "%s:%d: notice: unable to create ipbind '%s#%u': %s", __FILE__,
1759
0
          __LINE__, serv->ServerAddress, serv->ServerPort, strerror(errno));
1760
0
      }
1761
1762
0
      res = pr_ipbind_open(serv->addr, serv->ServerPort, NULL, is_default,
1763
0
        FALSE, TRUE);
1764
0
      if (res < 0) {
1765
0
        pr_log_pri(PR_LOG_NOTICE,
1766
0
          "%s:%d: notice: unable to open ipbind '%s': %s", __FILE__, __LINE__,
1767
0
          pr_netaddr_get_ipstr(serv->addr), strerror(errno));
1768
0
      }
1769
1770
0
      res = pr_ipbind_add_binds(serv);
1771
0
      if (res < 0) {
1772
0
        pr_log_pri(PR_LOG_NOTICE,
1773
0
          "%s:%d: notice: unable to add binds to ipbind '%s': %s", __FILE__,
1774
0
          __LINE__, serv->ServerAddress, strerror(errno));
1775
0
      }
1776
0
    }
1777
1778
    /* Process any ServerAlias directives AFTER the server's ipbind has been
1779
     * created/opened (Issue #932).
1780
     */
1781
0
    process_serveralias(serv);
1782
0
  }
1783
1784
0
  trace_ipbind_table();
1785
1786
  /* Any "unclaimed" listening conns can be removed and closed. */
1787
0
  if (listening_conn_list != NULL) {
1788
0
    struct listener_rec *lr, *lrn;
1789
1790
0
    for (lr = (struct listener_rec *) listening_conn_list->xas_list; lr; lr = lrn) {
1791
0
      pr_signals_handle();
1792
1793
0
      lrn = lr->next;
1794
0
      if (lr->claimed == FALSE) {
1795
0
        xaset_remove(listening_conn_list, (xasetmember_t *) lr);
1796
0
        destroy_pool(lr->pool);
1797
0
      }
1798
0
    }
1799
0
  }
1800
1801
0
  return 0;
1802
0
}
1803
1804
0
void init_bindings(void) {
1805
0
  int res = 0;
1806
1807
0
#ifdef PR_USE_IPV6
1808
0
  int sock;
1809
1810
  /* Check to see whether we can actually create an IPv6 socket. */
1811
0
  sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
1812
0
  if (sock < 0) {
1813
0
    pr_netaddr_disable_ipv6();
1814
1815
0
  } else {
1816
0
    (void) close(sock);
1817
0
  }
1818
0
#endif /* PR_USE_IPV6 */
1819
1820
0
  if (ServerType == SERVER_INETD) {
1821
0
    res = init_inetd_bindings();
1822
1823
0
  } else if (ServerType == SERVER_STANDALONE) {
1824
0
    res = init_standalone_bindings();
1825
0
  }
1826
1827
0
  if (res < 0) {
1828
0
    pr_log_pri(PR_LOG_ERR, "%s",
1829
0
      "Unable to start proftpd; check logs for more details");
1830
0
    exit(1);
1831
0
  }
1832
0
}