- /* Neuen Listen-Socket erzeugen: der Server wartet dann auf
- * dem angegebenen Port auf Verbindungen. Kann der Listen-
- * Socket nicht erteugt werden, so wird NULL geliefert.*/
-
- struct sockaddr_in addr;
- INT sock;
-
- /* Server-"Listen"-Socket initialisieren */
- memset( &addr, 0, sizeof( addr ));
- addr.sin_family = AF_INET;
- addr.sin_port = htons( Port );
- addr.sin_addr.s_addr = htonl( INADDR_ANY );
-
- /* Socket erzeugen */
- sock = socket( PF_INET, SOCK_STREAM, 0);
- if( sock < 0 )
- {
+ unsigned int created = 0;
+ size_t len;
+ int fd;
+ UINT16 *port;
+
+ len = array_length(a, sizeof (UINT16));
+ port = array_start(a);
+ while(len--) {
+ fd = NewListener(af, *port);
+ if (fd < 0) {
+ port++;
+ continue;
+ }
+ if (!io_event_create( fd, IO_WANTREAD, func )) {
+ Log( LOG_ERR, "io_event_create(): Could not add listening fd %d (port %u): %s!",
+ fd, (unsigned int) *port, strerror(errno));
+ close(fd);
+ port++;
+ continue;
+ }
+ created++;
+ port++;
+ }
+
+ return created;
+}
+
+
+GLOBAL unsigned int
+Conn_InitListeners( void )
+{
+ /* Initialize ports on which the server should accept connections */
+
+ unsigned int created = 0;
+
+ if (!io_library_init(CONNECTION_POOL)) {
+ Log(LOG_EMERG, "Cannot initialize IO routines: %s", strerror(errno));
+ return -1;
+ }
+
+#ifdef WANT_IPV6
+ if (Conf_ListenIPv6)
+ created = ports_initlisteners(&Conf_ListenPorts, AF_INET6, cb_listen);
+#endif
+ if (Conf_ListenIPv4)
+ created += ports_initlisteners(&Conf_ListenPorts, AF_INET, cb_listen);
+
+ return created;
+} /* Conn_InitListeners */
+
+
+GLOBAL void
+Conn_ExitListeners( void )
+{
+ /* Close down all listening sockets */
+ int *fd;
+ size_t arraylen;
+#ifdef ZEROCONF
+ Rendezvous_UnregisterListeners( );
+#endif
+
+ arraylen = array_length(&My_Listeners, sizeof (int));
+ Log( LOG_INFO, "Shutting down all listening sockets (%d total)...", arraylen );
+ fd = array_start(&My_Listeners);
+ while(arraylen--) {
+ assert(fd != NULL);
+ assert(*fd >= 0);
+ io_close(*fd);
+ LogDebug("Listening socket %d closed.", *fd );
+ fd++;
+ }
+ array_free(&My_Listeners);
+} /* Conn_ExitListeners */
+
+
+static bool
+InitSinaddrListenAddr(int af, ng_ipaddr_t *addr, UINT16 Port)
+{
+ bool ret;
+ const char *listen_addrstr = NULL;
+#ifdef WANT_IPV6
+ if (af == AF_INET)
+ listen_addrstr = "0.0.0.0";
+#else
+ (void)af;
+#endif
+ if (Conf_ListenAddress[0]) /* overrides V4/V6 atm */
+ listen_addrstr = Conf_ListenAddress;
+
+ ret = ng_ipaddr_init(addr, listen_addrstr, Port);
+ if (!ret) {
+ if (!listen_addrstr)
+ listen_addrstr = "";
+ Log(LOG_CRIT, "Can't bind to %s:%u: can't convert ip address \"%s\"",
+ listen_addrstr, Port, listen_addrstr);
+ }
+ return ret;
+}
+
+
+static void
+set_v6_only(int af, int sock)
+{
+#if defined(IPV6_V6ONLY) && defined(WANT_IPV6)
+ int on = 1;
+
+ if (af != AF_INET6)
+ return;
+
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)))
+ Log(LOG_ERR, "Could not set IPV6_V6ONLY: %s", strerror(errno));
+#else
+ (void)af;
+ (void)sock;
+#endif
+}
+
+
+/* return new listening port file descriptor or -1 on failure */
+static int
+NewListener(int af, const UINT16 Port)
+{
+ /* Create new listening socket on specified port */
+ ng_ipaddr_t addr;
+ int sock;
+#ifdef ZEROCONF
+ char name[CLIENT_ID_LEN], *info;
+#endif
+ if (!InitSinaddrListenAddr(af, &addr, Port))
+ return -1;
+
+ sock = socket(ng_ipaddr_af(&addr), SOCK_STREAM, 0);
+ if( sock < 0 ) {