Enable building #WITHOUT_PROXY
[freeradius.git] / src / main / listen.c
index c28d415..92c6fde 100644 (file)
@@ -201,7 +201,8 @@ RADCLIENT *client_listener_find(const rad_listen_t *listener,
                 *      can be defined.
                 */
                rad_assert(client->dynamic == 0);
-       } else {
+
+       } else if (!client->dynamic && client->rate_limit) {
                /*
                 *      The IP is unknown, so we've found an enclosing
                 *      network.  Enable DoS protection.  We only
@@ -619,7 +620,7 @@ static int auth_tcp_accept(rad_listen_t *listener,
 /*
  *     This function is stupid and complicated.
  */
-static int socket_print(rad_listen_t *this, char *buffer, size_t bufsize)
+static int socket_print(const rad_listen_t *this, char *buffer, size_t bufsize)
 {
        size_t len;
        listen_socket_t *sock = this->data;
@@ -724,6 +725,7 @@ static int socket_print(rad_listen_t *this, char *buffer, size_t bufsize)
                return 1;
        }
 
+#ifdef WITH_PROXY
        /*
         *      Maybe it's a socket that we opened to a home server.
         */
@@ -754,7 +756,8 @@ static int socket_print(rad_listen_t *this, char *buffer, size_t bufsize)
 
                return 1;
        }
-#endif
+#endif /* WITH_PROXY */
+#endif /* WITH_TCP */
 
        ADDSTRING(" address ");
        
@@ -781,6 +784,8 @@ static int socket_print(rad_listen_t *this, char *buffer, size_t bufsize)
        return 1;
 }
 
+extern int check_config;       /* radiusd.c */
+
 
 /*
  *     Parse an authentication or accounting socket.
@@ -865,18 +870,33 @@ static int common_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
                 *      TCP requires a destination IP for sockets.
                 *      UDP doesn't, so it's allowed.
                 */
+#ifdef WITH_PROXY
                if ((this->type == RAD_LISTEN_PROXY) &&
                    (sock->proto != IPPROTO_UDP)) {
                        cf_log_err(cf_sectiontoitem(cs),
                                   "Proxy listeners can only listen on proto = udp");
                        return -1;
                }
-#endif
+#endif /* WITH_PROXY */
+#endif /* WITH_TCP */
        }
 
        sock->my_ipaddr = ipaddr;
        sock->my_port = listen_port;
 
+       if (check_config) {
+               if (home_server_find(&sock->my_ipaddr, sock->my_port, sock->proto)) {
+                               char buffer[128];
+                               
+                               DEBUG("ERROR: We have been asked to listen on %s port %d, which is also listed as a home server.  This can create a proxy loop.",
+                                     ip_ntoh(&sock->my_ipaddr, buffer, sizeof(buffer)),
+                                     sock->my_port);
+                               return -1;
+               }
+
+               return 0;       /* don't do anything */
+       }
+
        /*
         *      If we can bind to interfaces, do so,
         *      else don't.
@@ -1816,7 +1836,7 @@ static const rad_listen_master_t master_listen[RAD_LISTEN_MAX] = {
 
 #ifdef WITH_COMMAND_SOCKET
        /* TCP command socket */
-       { command_socket_parse, NULL,
+       { command_socket_parse, command_socket_free,
          command_domain_accept, command_domain_send,
          command_socket_print, command_socket_encode, command_socket_decode },
 #endif
@@ -1913,7 +1933,7 @@ static int listen_bind(rad_listen_t *this)
 #endif
 
                default:
-                       radlog(L_ERR, "ERROR: Non-fatal internal sanity check failed in bind.");
+                       DEBUG("WARNING: Internal sanity check failed in binding to socket.  Ignoring problem.");
                        return -1;
                }
        }
@@ -2425,6 +2445,26 @@ static rad_listen_t *listen_parse(CONF_SECTION *cs, const char *server)
        return this;
 }
 
+static int is_loopback(const fr_ipaddr_t *ipaddr)
+{
+       /*
+        *      We shouldn't proxy on loopback.
+        */
+       if ((ipaddr->af == AF_INET) &&
+           (ipaddr->ipaddr.ip4addr.s_addr == htonl(INADDR_LOOPBACK))) {
+               return 1;
+       }
+       
+#ifdef HAVE_STRUCT_SOCKADDR_IN6
+       if ((ipaddr->af == AF_INET6) &&
+           (IN6_IS_ADDR_LINKLOCAL(&ipaddr->ipaddr.ip6addr))) {
+               return 1;
+       }
+#endif
+
+       return 0;
+}
+
 /*
  *     Generate a list of listeners.  Takes an input list of
  *     listeners, too, so we don't close sockets with waiting packets.
@@ -2651,6 +2691,15 @@ int listen_init(CONF_SECTION *config, rad_listen_t **head)
 
 add_sockets:
        /*
+        *      No sockets to receive packets, this is an error.
+        *      proxying is pointless.
+        */
+       if (!*head) {
+               radlog(L_ERR, "The server is not configured to listen on any ports.  Cannot start.");
+               return -1;
+       }
+
+       /*
         *      Print out which sockets we're listening on, and
         *      add them to the event list.
         */
@@ -2690,6 +2739,9 @@ add_sockets:
                for (this = *head; this != NULL; this = this->next) {
                        if (this->type == RAD_LISTEN_AUTH) {
                                sock = this->data;
+
+                               if (is_loopback(&sock->my_ipaddr)) continue;
+
                                if (home.src_ipaddr.af == AF_UNSPEC) {
                                        home.src_ipaddr = sock->my_ipaddr;
                                }
@@ -2699,6 +2751,9 @@ add_sockets:
 #ifdef WITH_ACCT
                        if (this->type == RAD_LISTEN_ACCT) {
                                sock = this->data;
+
+                               if (is_loopback(&sock->my_ipaddr)) continue;
+
                                if (home.src_ipaddr.af == AF_UNSPEC) {
                                        home.src_ipaddr = sock->my_ipaddr;
                                }
@@ -2758,12 +2813,12 @@ void listen_free(rad_listen_t **head)
                }
 
 #ifdef WITH_TCP
-               if ((this->type == RAD_LISTEN_AUTH) ||
+               if ((this->type == RAD_LISTEN_AUTH)
 #ifdef WITH_ACCT
-                   (this->type == RAD_LISTEN_ACCT) ||
+                   || (this->type == RAD_LISTEN_ACCT)
 #endif
 #ifdef WITH_PROXY
-                   (this->type == RAD_LISTEN_PROXY)
+                   || (this->type == RAD_LISTEN_PROXY)
 #endif
                        ) {
                        listen_socket_t *sock = this->data;
@@ -2826,18 +2881,9 @@ rad_listen_t *listener_find_byipaddr(const fr_ipaddr_t *ipaddr, int port)
                }
 
                if ((sock->my_port == port) &&
-                   ((sock->my_ipaddr.af == AF_INET) &&
-                    (sock->my_ipaddr.ipaddr.ip4addr.s_addr == INADDR_ANY))) {
-                       return this;
-               }
-
-#ifdef HAVE_STRUCT_SOCKADDR_IN6
-               if ((sock->my_port == port) &&
-                   (sock->my_ipaddr.af == AF_INET6) &&
-                   (IN6_IS_ADDR_UNSPECIFIED(&sock->my_ipaddr.ipaddr.ip6addr))) {
+                   fr_inaddr_any(&sock->my_ipaddr)) {
                        return this;
                }
-#endif
        }
 
        return NULL;