1 /*
2  * binding.c - server to port binding implementation
3  *
4  * Copyright (C) 2011-2013 Thien-Thi Nguyen
5  * Copyright (C) 2001, 2002 Stefan Jahn <stefan@lkcc.org>
6  *
7  * This is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  *
12  * This software is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this package.  If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #include "config.h"
22 
23 #include <stdio.h>
24 #include "timidity.h"
25 #include <string.h>
26 #include <sys/types.h>
27 
28 #ifndef __MINGW32__
29 # include <sys/socket.h>
30 #endif
31 #include "networking-headers.h"
32 #include "libserveez/alloc.h"
33 #include "libserveez/util.h"
34 #include "libserveez/socket.h"
35 #include "libserveez/core.h"
36 #include "libserveez/server.h"
37 #include "libserveez/server-core.h"
38 #include "libserveez/portcfg.h"
39 #include "libserveez/server-socket.h"
40 #include "libserveez/binding.h"
41 #include "libserveez/soprop.h"
42 
43 /*
44  * Hash table to map a socket to an array of bindings.
45  */
46 static svz_hash_t *all_ears;
47 
48 static void *
all_ears_x(const svz_socket_t * sock,svz_array_t * bindings)49 all_ears_x (const svz_socket_t *sock, svz_array_t *bindings)
50 {
51   return svz_soprop_put (all_ears, sock, bindings);
52 }
53 
54 svz_array_t *
svz_sock_bindings(const svz_socket_t * sock)55 svz_sock_bindings (const svz_socket_t *sock)
56 {
57   return svz_soprop_get (all_ears, sock);
58 }
59 
60 static int
portcfg_exactly_equal(svz_portcfg_t * a,svz_portcfg_t * b)61 portcfg_exactly_equal (svz_portcfg_t *a, svz_portcfg_t *b)
62 {
63   return SVZ_PORTCFG_EQUAL
64     == svz_portcfg_equal (a, b);
65 }
66 
67 static int
portcfg_matching_or_equal(svz_portcfg_t * a,svz_portcfg_t * b)68 portcfg_matching_or_equal (svz_portcfg_t *a, svz_portcfg_t *b)
69 {
70   return (SVZ_PORTCFG_EQUAL | SVZ_PORTCFG_MATCH)
71     & svz_portcfg_equal (a, b);
72 }
73 
74 /*
75  * Searches through the bindings of the given listening server socket
76  * structure @var{sock} and checks whether the server instance @var{server}
77  * is bound to this socket structure.  The function returns these binding and
78  * returns @code{NULL} otherwise.  The caller is responsible for freeing
79  * the returned array.
80  */
81 static svz_array_t *
from_server(svz_socket_t * sock,svz_server_t * server)82 from_server (svz_socket_t *sock, svz_server_t *server)
83 {
84   svz_array_t *bindings = svz_array_create (1, NULL);
85   svz_binding_t *binding;
86   size_t i;
87 
88   svz_array_foreach (svz_sock_bindings (sock), binding, i)
89     if (binding->server == server)
90       svz_array_add (bindings, binding);
91   return svz_array_destroy_zero (bindings);
92 }
93 
94 /**
95  * Return an array of port configurations to which the server instance
96  * @var{server} is currently bound to, or @code{NULL} if there is no such
97  * binding.  Caller should @code{svz_array_destroy} the returned array
98  * when done.
99  */
100 svz_array_t *
svz_server_portcfgs(svz_server_t * server)101 svz_server_portcfgs (svz_server_t *server)
102 {
103   svz_array_t *ports = svz_array_create (1, NULL);
104   svz_binding_t *binding;
105   svz_array_t *bindings;
106   svz_socket_t *sock;
107   size_t i;
108 
109   svz_sock_foreach_listener (sock)
110     if ((bindings = from_server (sock, server)) != NULL)
111       {
112         svz_array_foreach (bindings, binding, i)
113           svz_array_add (ports, binding->port);
114         svz_array_destroy (bindings);
115       }
116   return svz_array_destroy_zero (ports);
117 }
118 
119 /**
120  * Return an array of listening socket structures to which the server
121  * instance @var{server} is currently bound to, or @code{NULL} if there
122  * is no such binding.  Caller should @code{svz_array_destroy} the
123  * returned array when done.
124  */
125 svz_array_t *
svz_server_listeners(svz_server_t * server)126 svz_server_listeners (svz_server_t *server)
127 {
128   svz_array_t *listeners = svz_array_create (1, NULL);
129   svz_socket_t *sock;
130 
131   svz_sock_foreach_listener (sock)
132     if (svz_binding_contains_server (sock, server))
133       svz_array_add (listeners, sock);
134   return svz_array_destroy_zero (listeners);
135 }
136 
137 /*
138  * Returns a socket structure representing a listening server socket with
139  * the port configuration @var{port}.  If there is no such socket with this
140  * kind of port configuration yet then @code{NULL} is returned.
141  */
142 static svz_socket_t *
socket_with_portcfg(svz_portcfg_t * port)143 socket_with_portcfg (svz_portcfg_t *port)
144 {
145   svz_socket_t *sock;
146 
147   svz_sock_foreach_listener (sock)
148     if (portcfg_matching_or_equal (sock->port, port))
149       return sock;
150   return NULL;
151 }
152 
153 /*
154  * This functions goes through the list of listening server socket
155  * structures and returns an array of matching socket structures for the
156  * given port configuration @var{port}.  The caller is responsible for
157  * freeing the array by running @code{svz_array_destroy}.  If there are
158  * no such listening server socket structures @code{NULL} is returned.
159  */
160 static svz_array_t *
sockets_with_portcfg(svz_portcfg_t * port)161 sockets_with_portcfg (svz_portcfg_t *port)
162 {
163   svz_array_t *listeners = svz_array_create (1, NULL);
164   svz_socket_t *sock;
165 
166   svz_sock_foreach_listener (sock)
167     if (portcfg_matching_or_equal (sock->port, port))
168       svz_array_add (listeners, sock);
169   return svz_array_destroy_zero (listeners);
170 }
171 
172 /*
173  * Creates and returns a listening server socket structure.  The kind of
174  * listener which gets created depends on the given port configuration
175  * @var{port} which must be a duplicated copy of one out of the list of
176  * known port configurations.  On success the function enqueues the
177  * returned socket structure and assigns the port configuration.  Initially
178  * there are no bindings.  In case of an error the given port configuration
179  * is freed and @code{NULL} is returned.
180  */
181 static svz_socket_t *
make_listener_socket(svz_portcfg_t * port)182 make_listener_socket (svz_portcfg_t *port)
183 {
184   svz_socket_t *sock;
185 
186   /* Try creating a server socket.  */
187   if ((sock = svz_server_create (port)) != NULL)
188     {
189       /* Enqueue the server socket and put the port configuration into
190          the socket structure.  */
191       svz_sock_enqueue (sock);
192       sock->port = port;
193       return sock;
194     }
195 
196   /* Could not create this port configuration listener.  */
197   svz_portcfg_free (port);
198   return NULL;
199 }
200 
201 /*
202  * Creates a bind structure.  The binding contains the given server instance
203  * @var{server} and the port configuration @var{port}.  The caller is
204  * responsible for freeing the returned pointer.
205  */
206 static svz_binding_t *
make_binding(svz_server_t * server,svz_portcfg_t * port)207 make_binding (svz_server_t *server, svz_portcfg_t *port)
208 {
209   svz_binding_t *binding = svz_malloc (sizeof (svz_binding_t));
210   binding->server = server;
211   binding->port = port;
212   return binding;
213 }
214 
215 /*
216  * Goes through the listening server sockets @var{sock} bindings and checks
217  * whether it contains the given binding consisting of @var{server} and
218  * @var{port}.  If there is no such binding yet @code{NULL} is returned
219  * otherwise the appropriate binding.
220  */
221 static svz_binding_t *
find_binding(svz_socket_t * sock,svz_server_t * server,svz_portcfg_t * port)222 find_binding (svz_socket_t *sock, svz_server_t *server,
223               svz_portcfg_t *port)
224 {
225   svz_binding_t *binding;
226   size_t i;
227 
228   svz_array_foreach (svz_sock_bindings (sock), binding, i)
229     if (binding->server == server)
230       if (portcfg_exactly_equal (binding->port, port))
231         return binding;
232   return NULL;
233 }
234 
235 /*
236  * This function attaches the given server instance @var{server} to the
237  * listening socket structure @var{sock}.  It returns zero on success and
238  * non-zero if the server is already bound to the socket.
239  */
240 static int
add_server(svz_socket_t * sock,svz_server_t * server,svz_portcfg_t * port)241 add_server (svz_socket_t *sock, svz_server_t *server, svz_portcfg_t *port)
242 {
243   svz_binding_t *binding = make_binding (server, port);
244   svz_array_t *bindings = svz_sock_bindings (sock);
245 
246   /* Create server array if necessary.  */
247   if (bindings == NULL)
248     {
249       bindings = svz_array_create (1, (svz_free_func_t) svz_binding_destroy);
250       svz_array_add (bindings, binding);
251       all_ears_x (sock, bindings);
252       return 0;
253     }
254   /* Attach a server/port binding to a single listener only once.  */
255   else if (find_binding (sock, server, port) == NULL)
256     {
257       /* Extend the server array.  */
258       svz_array_add (bindings, binding);
259       return 0;
260     }
261   /* Binding already done.  */
262   svz_log (SVZ_LOG_WARNING, "skipped duplicate binding of `%s'\n", server->name);
263   svz_binding_destroy (binding);
264   return -1;
265 }
266 
267 /*
268  * Destroys the given binding @var{binding}.  This includes the explicit
269  * destruction of the port configuration.  If @var{binding} is @code{NULL}
270  * no operation is performed.
271  */
272 void
svz_binding_destroy(svz_binding_t * binding)273 svz_binding_destroy (svz_binding_t *binding)
274 {
275   if (binding != NULL)
276     {
277       svz_portcfg_free (binding->port);
278       svz_free (binding);
279     }
280 }
281 
282 /*
283  * This function checks whether the server instance binding @var{binding}
284  * is part of one of the bindings in the array @var{bindings} and returns
285  * non-zero if so.  Otherwise zero is returned.
286  */
287 static int
bindings_contain(svz_array_t * bindings,svz_binding_t * binding)288 bindings_contain (svz_array_t *bindings, svz_binding_t *binding)
289 {
290   svz_binding_t *search;
291   size_t i;
292 
293   svz_array_foreach (bindings, search, i)
294     if (search->server == binding->server)
295       if (portcfg_exactly_equal (search->port, binding->port))
296         return 1;
297   return 0;
298 }
299 
300 /*
301  * Returns the binding array of the listening server socket structure
302  * @var{sock} or @code{NULL} if there are no such bindings.
303  */
304 static svz_array_t *
sock_bindings(svz_socket_t * sock)305 sock_bindings (svz_socket_t *sock)
306 {
307   if (sock && sock->flags & SVZ_SOFLG_LISTENING && sock->port != NULL)
308     return svz_sock_bindings (sock);
309   return NULL;
310 }
311 
312 /*
313  * Make @var{sock} have no bindings.
314  */
315 void
svz_sock_bindings_set(svz_socket_t * sock,svz_socket_t * from)316 svz_sock_bindings_set (svz_socket_t *sock, svz_socket_t *from)
317 {
318   svz_array_t *bindings = from
319     ? svz_sock_bindings (from)
320     : NULL;
321 
322   all_ears_x (sock, bindings);
323 }
324 
325 /*
326  * Removes the server instance @var{server} from the listening socket
327  * structure @var{sock} and returns the remaining number of servers bound
328  * to the socket structure.
329  */
330 size_t
svz_sock_bindings_zonk_server(svz_socket_t * sock,svz_server_t * server)331 svz_sock_bindings_zonk_server (svz_socket_t *sock, svz_server_t *server)
332 {
333   svz_array_t *bindings = svz_sock_bindings (sock);
334   svz_binding_t *binding;
335   size_t i;
336 
337   svz_array_foreach (bindings, binding, i)
338     if (binding->server == server)
339       {
340         svz_binding_destroy (binding);
341         svz_array_del (bindings, i);
342         i--;
343       }
344   return svz_array_size (bindings);
345 }
346 
347 /*
348  * This function adds the bindings stored in the listening server socket
349  * structure @var{sock} to the binding array @var{bindings} and returns the
350  * resulting array.  If @var{bindings} is @code{NULL} a new array is created.
351  * If the socket structure @var{sock} is not a listening server socket
352  * structure no operation is performed.
353  */
354 static svz_array_t *
adjoin(svz_array_t * bindings,svz_socket_t * sock)355 adjoin (svz_array_t *bindings, svz_socket_t *sock)
356 {
357   svz_array_t *old = sock_bindings (sock);
358   svz_binding_t *binding;
359   size_t i;
360 
361   /* Is this a listening server socket?  */
362   if (!((sock->flags & SVZ_SOFLG_LISTENING) && (sock->port != NULL)))
363     return bindings;
364 
365   /* Create an array if necessary.  */
366   if (bindings == NULL)
367     bindings = svz_array_create (1, (svz_free_func_t) svz_binding_destroy);
368 
369   /* Join both arrays.  */
370   svz_array_foreach (old, binding, i)
371     if (!bindings_contain (bindings, binding))
372       {
373         svz_server_t *server = binding->server;
374         svz_portcfg_t *port = svz_portcfg_dup (binding->port);
375         svz_array_add (bindings, make_binding (server, port));
376       }
377 
378   /* Destroy the old bindings.  */
379   svz_array_destroy (old);
380 
381   /* Invalidate the binding array.  */
382   svz_sock_bindings_set (sock, NULL);
383   return bindings;
384 }
385 
386 /**
387  * Bind the server instance @var{server} to the port configuration
388  * @var{port} if possible.  Return non-zero on errors, otherwise zero.
389  * It might occur that a single server is bound to more than one network
390  * port if, e.g., the TCP/IP address is specified by @samp{*} (asterisk)
391  * since this gets expanded to the known list of interfaces.
392  */
393 int
svz_server_bind(svz_server_t * server,svz_portcfg_t * port)394 svz_server_bind (svz_server_t *server, svz_portcfg_t *port)
395 {
396   svz_array_t *ports;
397   svz_socket_t *sock;
398   svz_portcfg_t *copy, *portcfg;
399   size_t n, i;
400 
401   /* First expand the given port configuration.  */
402   ports = svz_portcfg_expand (port);
403   svz_array_foreach (ports, copy, n)
404     {
405       /* Prepare port configuration.  */
406       svz_portcfg_prepare (copy);
407 
408       /* Find appropriate socket structure for this port configuration.  */
409       if ((sock = socket_with_portcfg (copy)) == NULL)
410         {
411           if ((sock = make_listener_socket (copy)) != NULL)
412             add_server (sock, server, copy);
413         }
414       /* Port configuration already exists.  */
415       else
416         {
417           /* Is this a more general network port?  Is the new port an
418              INADDR_ANY binding and the picked one not?  */
419           portcfg = sock->port;
420           if ((copy->flags & PORTCFG_FLAG_ANY) &&
421               !(portcfg->flags & PORTCFG_FLAG_ANY))
422             {
423               svz_array_t *sockets = sockets_with_portcfg (port);
424               svz_array_t *bindings = NULL;
425               svz_socket_t *xsock;
426 
427               /* Join the bindings of the previous listeners and destroy
428                  these at once.  */
429               svz_log (SVZ_LOG_NOTICE, "destroying previous bindings\n");
430               svz_array_foreach (sockets, xsock, i)
431                 {
432                   bindings = adjoin (bindings, xsock);
433                   svz_sock_shutdown (xsock);
434                 }
435               svz_array_destroy (sockets);
436 
437               /* Create a fresh listener.  */
438               if ((sock = make_listener_socket (copy)) != NULL)
439                 {
440                   all_ears_x (sock, bindings);
441                   add_server (sock, server, copy);
442                 }
443               else
444                 {
445                   svz_array_destroy (bindings);
446                 }
447             }
448           /* No.  This is either a specific network interface or both have
449              an INADDR_ANY binding.  */
450           else
451             add_server (sock, server, copy);
452         }
453     }
454 
455   /* Now we can destroy the expanded port configuration array.  */
456   svz_array_destroy (ports);
457   return 0;
458 }
459 
460 /**
461  * Checks whether the server instance @var{server} is
462  * bound to the server socket structure @var{sock}.
463  * Return one if so, otherwise zero.
464  */
465 int
svz_binding_contains_server(svz_socket_t * sock,svz_server_t * server)466 svz_binding_contains_server (svz_socket_t *sock, svz_server_t *server)
467 {
468   svz_binding_t *binding;
469   size_t i;
470 
471   svz_array_foreach (svz_sock_bindings (sock), binding, i)
472     if (binding->server == server)
473       return 1;
474   return 0;
475 }
476 
477 /**
478  * Return the array of server instances bound to the listening
479  * @var{sock}, or @code{NULL} if there are no bindings.  Caller
480  * should @code{svz_array_destroy} the returned array when done.
481  */
482 svz_array_t *
svz_sock_servers(svz_socket_t * sock)483 svz_sock_servers (svz_socket_t *sock)
484 {
485   svz_array_t *servers = svz_array_create (1, NULL);
486   svz_array_t *bindings = sock_bindings (sock);
487   svz_binding_t *binding;
488   size_t i;
489 
490   svz_array_foreach (bindings, binding, i)
491     svz_array_add (servers, binding->server);
492   return svz_array_destroy_zero (servers);
493 }
494 
495 /*
496  * This is the accept filter for the listening server socket structures
497  * @var{sock} with pipe port configurations.  It returns all bindings.  The
498  * caller is responsible for freeing the returned array by running
499  * @code{svz_array_destroy}.
500  */
501 static svz_array_t *
filter_pipe(svz_socket_t * sock)502 filter_pipe (svz_socket_t *sock)
503 {
504   svz_array_t *filter = svz_array_create (1, NULL);
505   svz_array_t *bindings = svz_sock_bindings (sock);
506   svz_binding_t *binding;
507   size_t i;
508 
509   svz_array_foreach (bindings, binding, i)
510     svz_array_add (filter, binding);
511   return svz_array_destroy_zero (filter);
512 }
513 
514 /*
515  * This is the accept filter for the listening server socket structures
516  * @var{sock} with network port configurations.  It returns the bindings
517  * allowed to be accepted.  The caller is responsible for freeing the returned
518  * array by running @code{svz_array_destroy}.  Which of the bindings are
519  * allowed depends on the network interface address @var{addr} and the
520  * network port @var{port}.
521  */
522 static svz_array_t *
filter_net(svz_socket_t * sock,in_addr_t addr,in_port_t port)523 filter_net (svz_socket_t *sock, in_addr_t addr, in_port_t port)
524 {
525   svz_array_t *filter = svz_array_create (1, NULL);
526   svz_array_t *bindings = svz_sock_bindings (sock);
527   struct sockaddr_in *portaddr;
528   svz_binding_t *binding;
529   size_t i;
530 
531   /* Go through all bindings.  */
532   svz_array_foreach (bindings, binding, i)
533     {
534       portaddr = svz_portcfg_addr (binding->port);
535 #if DEVEL
536       printf ("portaddr: %s == ", svz_inet_ntoa (portaddr->sin_addr.s_addr));
537       printf ("%s\n", svz_inet_ntoa (addr));
538       printf ("port: %u == %u\n", ntohs (portaddr->sin_port), ntohs (port));
539 #endif
540       if (portaddr->sin_addr.s_addr == addr ||
541           binding->port->flags & (PORTCFG_FLAG_ANY | PORTCFG_FLAG_DEVICE))
542         {
543 #if DEVEL
544           printf ("addr ok\n");
545 #endif
546           if (binding->port->proto & (SVZ_PROTO_RAW | SVZ_PROTO_ICMP) ||
547               portaddr->sin_port == port)
548             {
549 #if DEVEL
550               printf ("port ok\n");
551 #endif
552               svz_array_add (filter, binding);
553             }
554         }
555     }
556   return svz_array_destroy_zero (filter);
557 }
558 
559 /*
560  * This function returns the local network address and port for the given
561  * client socket structure @var{sock}.  It returns non-zero if there no
562  * connection established.
563  */
564 static int
local_info(svz_socket_t * sock,in_addr_t * addr,in_port_t * port)565 local_info (svz_socket_t *sock, in_addr_t *addr, in_port_t *port)
566 {
567   struct sockaddr_in s;
568   socklen_t size = sizeof (s);
569 
570   if (!getsockname (sock->sock_desc, (struct sockaddr *) &s, &size))
571     {
572       if (addr)
573         *addr = s.sin_addr.s_addr;
574       if (port)
575         *port = s.sin_port;
576       return 0;
577     }
578   return -1;
579 }
580 
581 /*
582  * This is the main filter routine running either
583  * @code{filter_net} or @code{filter_pipe}
584  * depending on the type of port configuration the given socket @var{sock}
585  * contains.
586  */
587 svz_array_t *
svz_binding_filter(svz_socket_t * sock)588 svz_binding_filter (svz_socket_t *sock)
589 {
590   in_addr_t addr;
591   in_port_t port;
592 
593   if (sock->proto & SVZ_PROTO_PIPE)
594     return filter_pipe (sock);
595   if (local_info (sock, &addr, &port))
596     return NULL;
597   return filter_net (sock, addr, port);
598 }
599 
600 /**
601  * Format a space-separated list of current port configuration
602  * bindings for @var{server} into @var{buf}, which has @var{size}
603  * bytes.  The string is guaranteed to be nul-terminated.  Return the
604  * length (at most @code{@var{size} - 1}) of the formatted string.
605  */
606 size_t
svz_pp_server_bindings(char * buf,size_t size,svz_server_t * server)607 svz_pp_server_bindings (char *buf, size_t size, svz_server_t *server)
608 {
609   svz_socket_t *sock;
610   svz_array_t *bindings;
611   svz_binding_t *binding;
612   size_t i;
613   int lose = 0;
614   char *w = buf;
615   int firstp = 1;
616 
617   *w = '\0';
618 
619   /* Go through the list of socket structures.  */
620   svz_sock_foreach_listener (sock)
621     {
622       /* The server in the array of servers?  */
623       if ((bindings = from_server (sock, server)) != NULL)
624         {
625           /* Yes.  Get port configurations.  */
626           svz_array_foreach (bindings, binding, i)
627             {
628               char pretty[128];
629               size_t len = svz_pp_portcfg (pretty, 128, binding->port);
630 
631               if (size <= len + !firstp)
632                 {
633                   lose = 1;
634                   break;
635                 }
636               if (!firstp)
637                 {
638                   *w++ = ' ';
639                   size--;
640                 }
641               memcpy (w, pretty, len);
642               w += len;
643               size -= len;
644               firstp = 0;
645             }
646           svz_array_destroy (bindings);
647           *w = '\0';
648           if (lose)
649             goto out;
650         }
651     }
652 
653  out:
654   return w - buf;
655 }
656 
657 
658 void
zonk_sock_ears(const svz_socket_t * sock)659 zonk_sock_ears (const svz_socket_t *sock)
660 {
661   if (sock->flags & SVZ_SOFLG_LISTENING)
662     {
663       svz_array_t *bindings = all_ears_x (sock, NULL);
664 
665       if (bindings != NULL)
666         svz_array_destroy (bindings);
667     }
668 }
669 
670 void
svz__bindings_updn(int direction)671 svz__bindings_updn (int direction)
672 {
673   if (direction)
674     {
675       /* We don't specify DESTROY to ‘svz_soprop_create’ because the value
676          (bindings array) is shared by the listener socket w/ those derived
677          from it.  Unsharing is implemented by discarding the reference,
678          w/o destroying the bindings.  Bindings destruction happens only
679          when the listener socket is destroyed (see ‘zonk_sock_ears’).  */
680       all_ears = svz_soprop_create (1, NULL);
681       svz_sock_prefree (1, zonk_sock_ears);
682     }
683   else
684     {
685       svz_sock_prefree (0, zonk_sock_ears);
686       svz_soprop_destroy (all_ears);
687       all_ears = NULL;
688     }
689 }
690