1 /* 2 * ProFTPD - FTP server daemon 3 * Copyright (c) 2001-2020 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 /* ProFTPD bindings support routines. */ 26 27 #ifndef PR_BINDINGS_H 28 #define PR_BINDINGS_H 29 30 #include "conf.h" 31 #include "pool.h" 32 33 /* NOTE: the is* members could possibly become a bitmasked number */ 34 35 /* Structure associating an IP address to a server_rec */ 36 typedef struct ipbind_rec { 37 struct ipbind_rec *ib_next; 38 39 /* IP address to which this binding is "bound" */ 40 const pr_netaddr_t *ib_addr; 41 unsigned int ib_port; 42 43 /* Default server to handle requests to this binding. If namebinds are 44 * present, they will be checked before using this server 45 */ 46 server_rec *ib_server; 47 48 /* Listener associated with this binding. This listener, and 49 * ib_server->listen, are the same listener. The duplicate locations 50 * are necessary for inetd-run servers (at present). 51 */ 52 conn_t *ib_listener; 53 54 /* List of name-based servers bound to the above IP address. Note that 55 * if this functionality becomes widely adopted and used, a more efficient 56 * search-and-lookup mechanism will be needed, for performance reasons. 57 */ 58 array_header *ib_namebinds; 59 60 /* If this binding is the DefaultServer binding */ 61 unsigned char ib_isdefault; 62 63 /* If this binding handles localhost requests */ 64 unsigned char ib_islocalhost; 65 66 /* If this binding is active */ 67 unsigned char ib_isactive; 68 69 } pr_ipbind_t; 70 71 /* Structure associating a name to a server_rec */ 72 typedef struct namebind_rec { 73 const char *nb_name; 74 unsigned char nb_iswildcard; 75 unsigned char nb_isactive; 76 server_rec *nb_server; 77 unsigned int nb_server_port; 78 79 } pr_namebind_t; 80 81 /* Define the size of the hash table used to store server configurations. 82 * It needs to be a power of two. 83 */ 84 #define PR_BINDINGS_TABLE_SIZE 256 85 86 /* Given an fd returned by select(), accept() and return the connt_t structure 87 * for the binding associated with that fd. Returns the conn_t if successful, 88 * NULL if not found or if the arguments were NULL. 89 */ 90 conn_t *pr_ipbind_accept_conn(fd_set *readfds, int *listenfd); 91 92 /* Create a new IP-based binding for the server given, using the provided 93 * arguments. The new binding is added the list maintained by the bindings 94 * layer. Returns 0 on success, -1 on failure. 95 */ 96 int pr_ipbind_create(server_rec *server, const pr_netaddr_t *addr, 97 unsigned int port); 98 99 /* Close all IP bindings associated with the given IP address/port combination. 100 * The bindings are then marked as inactive, so that future lookups via 101 * pr_ipbind_find() skip these bindings. Returns 0 on success, -1 on failure 102 * (eg no associated bindings found). 103 */ 104 int pr_ipbind_close(const pr_netaddr_t *addr, unsigned int port, 105 unsigned char close_namebinds); 106 107 /* Close all listenings fds. This needs to happen just after a process 108 * has been forked to handle a session. 109 */ 110 int pr_ipbind_close_listeners(void); 111 112 /* Search through the given server's configuration records, and for each 113 * associated bind configuration found, create an additional IP binding for 114 * that bind address. Honors SocketBindTight, if set. Returns 0 on 115 * success, -1 on failure (if server == NULL, for example). 116 */ 117 int pr_ipbind_add_binds(server_rec *server); 118 119 /* Search the binding list, and return the pr_ipbind_t for the given addr and 120 * port. If requested, skip over inactive bindings while searching. 121 */ 122 pr_ipbind_t *pr_ipbind_find(const pr_netaddr_t *addr, unsigned int port, 123 unsigned char skip_inactive); 124 125 /* Iterate through the binding list, returning the next ipbind. Returns NULL 126 * once the end of the list is reached. If prev is NULL, the iterator 127 * restarts at the beginning of the list. 128 */ 129 pr_ipbind_t *pr_ipbind_get(pr_ipbind_t *prev); 130 131 /* Search the binding list, and return the server_rec * that is bound to the 132 * given IP address/port combination. 133 */ 134 server_rec *pr_ipbind_get_server(const pr_netaddr_t *addr, unsigned int port); 135 136 /* Listens on each file descriptor in the given set, and returns the file 137 * descriptor associated with an incoming connection request. Returns -1 138 * on error, as when the fd_set argument is NULL. 139 */ 140 int pr_ipbind_listen(fd_set *readfds); 141 142 /* Prepares the IP-based binding associated with the given server for listening. 143 * Returns 0 on success, -1 on failure. 144 */ 145 int pr_ipbind_open(const pr_netaddr_t *addr, unsigned int port, 146 conn_t *listen_conn, unsigned char isdefault, unsigned char islocalhost, 147 unsigned char open_namebinds); 148 149 conn_t *pr_ipbind_get_listening_conn(server_rec *server, 150 const pr_netaddr_t *addr, unsigned int port); 151 152 /* Close the pr_namebind_t with the given name. */ 153 int pr_namebind_close(const char *name, const pr_netaddr_t *addr); 154 155 /* Create a pr_namebind_t, similar to a pr_ipbind_t, which maps the name (usu. 156 * DNS hostname) to the server_rec. The given addr is used to associate this 157 * pr_namebind_t with the given IP address (to which the DNS hostname should 158 * resolve). 159 */ 160 int pr_namebind_create(server_rec *server, const char *name, 161 pr_ipbind_t *ipbind, const pr_netaddr_t *addr, unsigned int port); 162 163 /* Search the Bindings layer, and return the pr_namebind_t associated with 164 * the given addr, port, and name. If requested, skip over inactive 165 * bindings while searching. 166 */ 167 pr_namebind_t *pr_namebind_find(const char *name, const pr_netaddr_t *addr, 168 unsigned int port, unsigned char skip_inactive); 169 170 /* Find the server_rec associated with the given name. If none are found, 171 * default to the server_rec of the containing pr_ipbind_t. 172 */ 173 server_rec *pr_namebind_get_server(const char *name, const pr_netaddr_t *addr, 174 unsigned int port); 175 176 /* Opens the pr_namebind_t with the given name. */ 177 int pr_namebind_open(const char *name, const pr_netaddr_t *addr, 178 unsigned int port); 179 180 /* Provides a count of the number of namebinds associated with this 181 * server_rec. 182 */ 183 unsigned int pr_namebind_count(server_rec *); 184 185 /* Initialize the Bindings layer. */ 186 void init_bindings(void); 187 188 /* Free the Bindings layer. */ 189 void free_bindings(void); 190 191 /* Macro error-handling wrappers */ 192 #define PR_ADD_IPBINDS(s) \ 193 if ((res = pr_ipbind_add_binds((s))) < 0) \ 194 pr_log_pri(PR_LOG_NOTICE, \ 195 "%s:%d: notice: unable to add binds to ipbind '%s': %s", \ 196 __FILE__, __LINE__, (s)->ServerAddress, strerror(errno)) 197 198 #define PR_CLOSE_IPBIND(a, p, c) \ 199 if ((res = pr_ipbind_close((a), (p), (c))) < 0) \ 200 pr_log_pri(PR_LOG_NOTICE, \ 201 "%s:%d: notice: unable to close ipbind: %s", \ 202 __FILE__, __LINE__, strerror(errno)) 203 204 #define PR_CREATE_IPBIND(s, a, p) \ 205 if ((res = pr_ipbind_create((s), (a), (p))) < 0) \ 206 pr_log_pri(PR_LOG_NOTICE, \ 207 "%s:%d: notice: unable to create ipbind '%s#%u': %s", \ 208 __FILE__, __LINE__, (s)->ServerAddress, (p), strerror(errno)) 209 210 #define PR_OPEN_IPBIND(a, p, c, d, l, o) \ 211 if ((res = pr_ipbind_open((a), (p), (c), (d), (l), (o))) < 0) \ 212 pr_log_pri(PR_LOG_NOTICE, \ 213 "%s:%d: notice: unable to open ipbind '%s': %s", \ 214 __FILE__, __LINE__, pr_netaddr_get_ipstr((a)), strerror(errno)) 215 216 #endif /* PR_BINDINGS_H */ 217