Signed / unsigned fixes and function prototypes
[freeradius.git] / src / main / realms.c
index 7ca336c..37ceb48 100644 (file)
@@ -182,6 +182,36 @@ static int home_pool_name_cmp(const void *one, const void *two)
 }
 
 
+static size_t xlat_cs(CONF_SECTION *cs, char *fmt, char *out, size_t outlen)
+
+{
+       const char *value = NULL;
+
+       /*
+        *      Instance name
+        */
+       if (strcmp(fmt, "instance") == 0) {
+               value = cf_section_name2(cs);
+               if (!value) {
+                       *out = '\0';
+                       return 0;
+               }
+       } else {
+               CONF_PAIR *cp;
+
+               cp = cf_pair_find(cs, fmt);
+               if (!cp || !(value = cf_pair_value(cp))) {
+                       *out = '\0';
+                       return 0;
+               }
+       }
+
+       strlcpy(out, value, outlen);
+
+       return strlen(out);
+}
+
+
 /*
  *     Xlat for %{home_server:foo}
  */
@@ -189,9 +219,6 @@ static size_t xlat_home_server(UNUSED void *instance, REQUEST *request,
                               char *fmt, char *out, size_t outlen,
                               UNUSED RADIUS_ESCAPE_STRING func)
 {
-       const char *value = NULL;
-       CONF_PAIR *cp;
-
        if (!fmt || !out || (outlen < 1)) return 0;
 
        if (!request || !request->home_server) {
@@ -199,15 +226,7 @@ static size_t xlat_home_server(UNUSED void *instance, REQUEST *request,
                return 0;
        }
 
-       cp = cf_pair_find(request->home_server->cs, fmt);
-       if (!cp || !(value = cf_pair_value(cp))) {
-               *out = '\0';
-               return 0;
-       }
-       
-       strlcpy(out, value, outlen);
-
-       return strlen(out);
+       return xlat_cs(request->home_server->cs, fmt, out, outlen);
 }
 
 
@@ -218,9 +237,6 @@ static size_t xlat_server_pool(UNUSED void *instance, REQUEST *request,
                               char *fmt, char *out, size_t outlen,
                               UNUSED RADIUS_ESCAPE_STRING func)
 {
-       const char *value = NULL;
-       CONF_PAIR *cp;
-
        if (!fmt || !out || (outlen < 1)) return 0;
 
        if (!request || !request->home_pool) {
@@ -228,15 +244,7 @@ static size_t xlat_server_pool(UNUSED void *instance, REQUEST *request,
                return 0;
        }
 
-       cp = cf_pair_find(request->home_pool->cs, fmt);
-       if (!cp || !(value = cf_pair_value(cp))) {
-               *out = '\0';
-               return 0;
-       }
-       
-       strlcpy(out, value, outlen);
-
-       return strlen(out);
+       return xlat_cs(request->home_pool->cs, fmt, out, outlen);
 }
 #endif
 
@@ -387,6 +395,10 @@ static CONF_PARSER home_server_config[] = {
 };
 
 
+static void null_free(UNUSED void *data)
+{
+}
+
 static int home_server_add(realm_config_t *rc, CONF_SECTION *cs, int pool_type)
 {
        const char *name2;
@@ -417,6 +429,13 @@ static int home_server_add(realm_config_t *rc, CONF_SECTION *cs, int pool_type)
        home->name = name2;
        home->cs = cs;
 
+        /*
+        *      For zombie period calculations.  We want to count
+        *      zombies from the time when the server starts, instead
+        *      of from 1970.
+        */
+       home->last_packet = time(NULL);
+
        /*
         *      Authentication servers have a default "no_response_fail = 0".
         *      Accounting servers have a default "no_response_fail = 1".
@@ -521,7 +540,7 @@ static int home_server_add(realm_config_t *rc, CONF_SECTION *cs, int pool_type)
                if (pool_type != home->type) {
                mismatch:
                        cf_log_err(cf_sectiontoitem(cs),
-                                  "Server pool cannot include home server %s of type \"%s\"",
+                                  "Home server %s of unexpected type \"%s\"",
                                   name2, hs_type);
                        goto error;
                }
@@ -776,6 +795,11 @@ static int home_server_add(realm_config_t *rc, CONF_SECTION *cs, int pool_type)
 #endif
        }
 
+       /*
+        *      Mark it as already processed
+        */
+       cf_data_add(cs, "home_server", null_free, null_free);
+
        return 1;
 }
 
@@ -1572,15 +1596,22 @@ static int realm_add(realm_config_t *rc, CONF_SECTION *cs)
 
 #ifdef HAVE_REGEX_H
        if (name2[0] == '~') {
+               int rcode;
                regex_t reg;
                
                /*
                 *      Include substring matches.
                 */
-               if (regcomp(&reg, name2 + 1,
-                           REG_EXTENDED | REG_NOSUB | REG_ICASE) != 0) {
+               rcode = regcomp(&reg, name2 + 1,
+                               REG_EXTENDED | REG_NOSUB | REG_ICASE);
+               if (rcode != 0) {
+                       char buffer[256];
+
+                       regerror(rcode, &reg, buffer, sizeof(buffer));
+
                        cf_log_err(cf_sectiontoitem(cs),
-                                  "Invalid regex in realm \"%s\"", name2);
+                                  "Invalid regex \"%s\": %s",
+                                  name2 + 1, buffer);
                        goto error;
                }
                regfree(&reg);
@@ -1816,6 +1847,22 @@ int realms_init(CONF_SECTION *config)
                        return 0;
                }
        }
+
+       /*
+        *      CoA home servers aren't tied to realms.
+        */
+       for (cs = cf_subsection_find_next(config, NULL, "home_server");
+            cs != NULL;
+            cs = cf_subsection_find_next(config, cs, "home_server")) {
+               /*
+                *      Server was already loaded.
+                */
+               if (cf_data_find(cs, "home_server")) continue;
+
+               if (!home_server_add(rc, cs, HOME_TYPE_COA)) {
+                       return 0;
+               }
+       }
 #endif
 
 
@@ -1975,7 +2022,7 @@ home_server *home_server_ldb(const char *realmname,
                break;
 
        case HOME_POOL_KEYED_BALANCE:
-               if ((vp = pairfind(request->config_items, PW_LOAD_BALANCE_KEY)) != NULL) {
+               if ((vp = pairfind(request->config_items, PW_LOAD_BALANCE_KEY, 0)) != NULL) {
                        hash = fr_hash(vp->vp_strvalue, vp->length);
                        start = hash % pool->num_home_servers;
                        break;
@@ -2147,11 +2194,6 @@ home_server *home_server_ldb(const char *realmname,
                         *      the 'hints' file.
                         */
                        request->proxy->vps =  paircopy(request->packet->vps);
-
-                       /*
-                        *      Set the source IP address for proxying.
-                        */
-                       request->proxy->src_ipaddr = found->src_ipaddr;
                }
 
                /*
@@ -2169,7 +2211,7 @@ home_server *home_server_ldb(const char *realmname,
                 */
                if (found->message_authenticator &&
                    (request->packet->code == PW_AUTHENTICATION_REQUEST) &&
-                   !pairfind(request->proxy->vps, PW_MESSAGE_AUTHENTICATOR)) {
+                   !pairfind(request->proxy->vps, PW_MESSAGE_AUTHENTICATOR, 0)) {
                        radius_pairmake(request, &request->proxy->vps,
                                        "Message-Authenticator", "0x00",
                                        T_OP_SET);