Add radius_get_vps function to find attribute list based on <list>:<attribute> attrib...
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 3 Nov 2011 16:19:51 +0000 (17:19 +0100)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 4 Nov 2011 13:48:32 +0000 (14:48 +0100)
src/include/radiusd.h
src/main/valuepair.c

index c1d665d..203519b 100644 (file)
@@ -317,6 +317,25 @@ struct auth_req {
 
 typedef struct radclient_list RADCLIENT_LIST;
 
+typedef enum pair_lists {
+       PAIR_LIST_UNKNOWN = 0,
+       PAIR_LIST_REQUEST,
+       PAIR_LIST_REPLY,
+       PAIR_LIST_CONTROL,
+#ifdef WITH_PROXY
+       PAIR_LIST_PROXY_REQUEST,
+       PAIR_LIST_PROXY_REPLY,
+#endif
+#ifdef WITH_COA
+       PAIR_LIST_COA,
+       PAIR_LIST_COA_REPLY,
+       PAIR_LIST_DM,
+       PAIR_LIST_DM_REPLY
+#endif
+} pair_lists_t;
+
+extern const FR_NAME_NUMBER pair_lists[];
+
 typedef struct pair_list {
        const char              *name;
        VALUE_PAIR              *check;
@@ -327,7 +346,6 @@ typedef struct pair_list {
        struct pair_list        *lastdefault;
 } PAIR_LIST;
 
-
 typedef int (*rad_listen_recv_t)(rad_listen_t *);
 typedef int (*rad_listen_send_t)(rad_listen_t *, REQUEST *);
 typedef int (*rad_listen_print_t)(const rad_listen_t *, char *, size_t);
@@ -747,6 +765,10 @@ int radius_update_attrlist(REQUEST *request, CONF_SECTION *cs,
                           VALUE_PAIR *input_vps, const char *name);
 void radius_pairmove(REQUEST *request, VALUE_PAIR **to, VALUE_PAIR *from);
 int radius_get_vp(REQUEST *request, const char *name, VALUE_PAIR **vp_p);
+int radius_get_vps(REQUEST *request, const char *name,
+       VALUE_PAIR **vps, const char **attr);
+
+
 
 #ifdef WITH_TLS
 /*
index 091ee41..e995bf2 100644 (file)
@@ -51,6 +51,24 @@ RCSID("$Id$")
 #endif
 #endif
 
+const FR_NAME_NUMBER pair_lists[] = {
+       { "request",            PAIR_LIST_REQUEST },
+       { "reply",              PAIR_LIST_REPLY },
+       { "config",             PAIR_LIST_CONTROL },
+       { "control",            PAIR_LIST_CONTROL },
+#ifdef WITH_PROXY
+       { "proxy-request",      PAIR_LIST_PROXY_REQUEST },
+       { "proxy-reply",        PAIR_LIST_PROXY_REPLY },        
+#endif
+#ifdef WITH_COA
+       { "coa",                PAIR_LIST_COA },
+       { "coa-reply",          PAIR_LIST_COA_REPLY },
+       { "disconnect",         PAIR_LIST_DM },
+       { "disconnect-reply",   PAIR_LIST_DM_REPLY },
+#endif
+       {  NULL , -1 }
+};
+
 struct cmp {
        unsigned int attribute;
        unsigned int otherattr;
@@ -823,92 +841,128 @@ void debug_pair_list(VALUE_PAIR *vp)
        fflush(fr_log_fp);
 }
 
-
-int radius_get_vp(REQUEST *request, const char *name, VALUE_PAIR **vp_p)
-{
-       const char *vp_name = name;
-       REQUEST *myrequest = request;
-       DICT_ATTR *da;
-       VALUE_PAIR *vps = NULL;
-
-       *vp_p = NULL;
+/** @brief Resolve attribute qualifiers to an attribute list
+ *
+ * @param request The current request
+ * @param name Attribute name including qualifiers
+ * @param vps Where to write the pointer to resolved list. Will be NULL if list name
+ * couldn't be resolved, or is invalid in the current context
+ * @param attribute Where to write pointer into name (name minus qualifiers)
+ * @return False if the list qualifiers were invalid, else true
+ */
+int radius_get_vps(REQUEST *request, const char *name,
+       VALUE_PAIR **vps, const char **attribute){
+       REQUEST *my_request;
+       
+       const char *p = name;
+       const char *q;
+       
+       *vps = NULL;
+       *attribute = p;
+       
+       pair_lists_t list;
 
        /*
         *      Allow for tunneled sessions.
         */
-       if (strncmp(vp_name, "outer.", 6) == 0) {
-               if (!myrequest->parent) return TRUE;
-               vp_name += 6;
-               myrequest = myrequest->parent;
+       if (strncmp(p, "outer.", 6) == 0) {
+               if (!request->parent) return TRUE;
+               p += 6;
+               my_request = request->parent;
        }
 
-       if (strncmp(vp_name, "request:", 8) == 0) {
-               vp_name += 8;
-               vps = myrequest->packet->vps;
-
-       } else if (strncmp(vp_name, "reply:", 6) == 0) {
-               vp_name += 6;
-               vps = myrequest->reply->vps;
+       q = strchr(p, ':');
+       if (q == NULL) {
+               *vps = my_request->packet->vps;
+               *attribute = p;
+               return TRUE;
+       }
+       *attribute = q + 1;
 
-#ifdef WITH_PROXY
-       } else if (strncmp(vp_name, "proxy-request:", 14) == 0) {
-               vp_name += 14;
-               if (request->proxy) vps = myrequest->proxy->vps;
+       list = fr_substr2int(pair_lists, p, PAIR_LIST_UNKNOWN, q - p);
+       switch (list) {
+               case PAIR_LIST_REQUEST:
+                       *vps = my_request->packet->vps;
+                       break;
 
-       } else if (strncmp(vp_name, "proxy-reply:", 12) == 0) {
-               vp_name += 12;
-               if (request->proxy_reply) vps = myrequest->proxy_reply->vps;
-#endif
+               case PAIR_LIST_REPLY:
+                       *vps = my_request->reply->vps;
+                       break;
 
-       } else if (strncmp(vp_name, "config:", 7) == 0) {
-               vp_name += 7;
-               vps = myrequest->config_items;
+               case PAIR_LIST_CONTROL:
+                       *vps = my_request->config_items;
+                       break;
 
-       } else if (strncmp(vp_name, "control:", 8) == 0) {
-               vp_name += 8;
-               vps = myrequest->config_items;
+#ifdef WITH_PROXY              
+               case PAIR_LIST_PROXY_REQUEST:
+                       *vps = my_request->proxy->vps;
+                       break;
 
+               case PAIR_LIST_PROXY_REPLY:
+                       *vps = my_request->proxy_reply->vps;
+                       break;
+#endif
 #ifdef WITH_COA
-       } else if (strncmp(vp_name, "coa:", 4) == 0) {
-               vp_name += 4;
-
-               if (myrequest->coa &&
-                   (myrequest->coa->proxy->code == PW_COA_REQUEST)) {
-                       vps = myrequest->coa->proxy->vps;
-               }
+               case PAIR_LIST_COA:
+                       if (my_request->coa &&
+                          (my_request->coa->proxy->code == PW_COA_REQUEST))
+                               *vps = my_request->coa->proxy->vps;
+                               
+                       break;
 
-       } else if (strncmp(vp_name, "coa-reply:", 10) == 0) {
-               vp_name += 10;
+               case PAIR_LIST_COA_REPLY:
+                       if (my_request->coa && /* match reply with request */
+                          (my_request->coa->proxy->code == PW_COA_REQUEST) &&
+                           my_request->coa->proxy_reply)
+                               *vps = my_request->coa->proxy_reply->vps;
+                       
+                       break;
 
-               if (myrequest->coa && /* match reply with request */
-                   (myrequest->coa->proxy->code == PW_COA_REQUEST) &&
-                   (myrequest->coa->proxy_reply)) {
-                       vps = myrequest->coa->proxy_reply->vps;
-               }
+               case PAIR_LIST_DM:
+                       if (my_request->coa &&
+                          (my_request->coa->proxy->code == PW_DISCONNECT_REQUEST))
+                               *vps = my_request->coa->proxy->vps;
+                       
+                       break;
 
-       } else if (strncmp(vp_name, "disconnect:", 11) == 0) {
-               vp_name += 11;
+               case PAIR_LIST_DM_REPLY:
+                       if (my_request->coa && /* match reply with request */
+                          (my_request->coa->proxy->code == PW_DISCONNECT_REQUEST) &&
+                           my_request->coa->proxy_reply)
+                               *vps = my_request->coa->proxy->vps;
+                       break;
+#endif
+               default:
+                       return FALSE;
 
-               if (myrequest->coa &&
-                   (myrequest->coa->proxy->code == PW_DISCONNECT_REQUEST)) {
-                       vps = myrequest->coa->proxy->vps;
-               }
+       }
+       return TRUE;
+}
 
-       } else if (strncmp(vp_name, "disconnect-reply:", 17) == 0) {
-               vp_name += 17;
+/** @brief Return a VP from the specified request
+ *
+ * @param request The current request
+ * @param name Attribute name including qualifiers
+ * @param vp_p Where to write the pointer to the resolved VP. Will be NULL if the attribute
+ * couldn't be resolved
+ * @return False if either the attribute or qualifier were invalid, else true
+ */
+int radius_get_vp(REQUEST *request, const char *name, VALUE_PAIR **vp_p)
+{
+       const char *attribute;
+       
+       VALUE_PAIR *vps = NULL;
+       DICT_ATTR *da;
+       
+       int ret;
 
-               if (myrequest->coa && /* match reply with request */
-                   (myrequest->coa->proxy->code == PW_DISCONNECT_REQUEST) &&
-                   (myrequest->coa->proxy_reply)) {
-                       vps = myrequest->coa->proxy_reply->vps;
-               }
-#endif
+       *vp_p = NULL;
 
-       } else {
-               vps = myrequest->packet->vps;
-       }
+       ret = radius_get_vps(request, name, &vps, &attribute);
+       if (!ret) return FALSE; /* not a valid attribute list */
+       if (!vps) return TRUE;  /* list is valid but not in current context */
 
-       da = dict_attrbyname(vp_name);
+       da = dict_attrbyname(attribute);
        if (!da) return FALSE;  /* not a dictionary name */
 
        /*