Signed / unsigned fixes and function prototypes
[freeradius.git] / src / lib / valuepair.c
index c6ec090..57fe9a2 100644 (file)
@@ -134,6 +134,34 @@ VALUE_PAIR *pairalloc(DICT_ATTR *da)
        return vp;
 }
 
+/*
+ *     Create a new valuepair.
+ */
+VALUE_PAIR *paircreate_raw(int attr, int vendor, int type, VALUE_PAIR *vp)
+{
+       char *p = (char *) (vp + 1);
+
+       if (!vp->flags.unknown_attr) {
+               pairfree(&vp);
+               return NULL;
+       }
+
+       vp->vendor = vendor;
+       vp->attribute = attr;
+       vp->operator = T_OP_EQ;
+       vp->name = p;
+       vp->type = type;
+       vp->length = 0;
+       memset(&vp->flags, 0, sizeof(vp->flags));
+       vp->flags.unknown_attr = 1;
+       
+       if (!vp_print_name(p, FR_VP_NAME_LEN, vp->attribute, vp->vendor)) {
+               free(vp);
+               return NULL;
+       }
+
+       return vp;
+}
 
 /*
  *     Create a new valuepair.
@@ -153,19 +181,7 @@ VALUE_PAIR *paircreate(int attr, int vendor, int type)
        /*
         *      It isn't in the dictionary: update the name.
         */
-       if (!da) {
-               char *p = (char *) (vp + 1);
-               
-               vp->vendor = vendor;
-               vp->attribute = attr;
-               vp->name = p;
-               vp->type = type; /* be forgiving */
-
-               if (!vp_print_name(p, FR_VP_NAME_LEN, attr, vendor)) {
-                       free(vp);
-                       return NULL;
-               }
-       }
+       if (!da) return paircreate_raw(attr, vendor, type, vp);
 
        return vp;
 }
@@ -206,7 +222,7 @@ void pairfree(VALUE_PAIR **pair_ptr)
 /*
  *     Find the pair with the matching attribute
  */
-VALUE_PAIR * pairfind(VALUE_PAIR *first, int attr, int vendor)
+VALUE_PAIR * pairfind(VALUE_PAIR *first, unsigned int attr, unsigned int vendor)
 {
        while (first) {
                if ((first->attribute == attr) && (first->vendor == vendor)) {
@@ -222,7 +238,7 @@ VALUE_PAIR * pairfind(VALUE_PAIR *first, int attr, int vendor)
 /*
  *     Delete the pair(s) with the matching attribute
  */
-void pairdelete(VALUE_PAIR **first, int attr, int vendor)
+void pairdelete(VALUE_PAIR **first, unsigned int attr, unsigned int vendor)
 {
        VALUE_PAIR *i, *next;
        VALUE_PAIR **last = first;
@@ -326,6 +342,13 @@ VALUE_PAIR *paircopyvp(const VALUE_PAIR *vp)
                return NULL;
        }
        memcpy(n, vp, sizeof(*n) + name_len);
+
+       /*
+        *      Reset the name field to point to the NEW attribute,
+        *      rather than to the OLD one.
+        */
+       if (vp->flags.unknown_attr) n->name = (char *) (n + 1);
+
        n->next = NULL;
 
        if ((n->type == PW_TYPE_TLV) &&
@@ -341,7 +364,7 @@ VALUE_PAIR *paircopyvp(const VALUE_PAIR *vp)
 /*
  *     Copy just a certain type of pairs.
  */
-VALUE_PAIR *paircopy2(VALUE_PAIR *vp, int attr, int vendor)
+VALUE_PAIR *paircopy2(VALUE_PAIR *vp, unsigned int attr, unsigned int vendor)
 {
        VALUE_PAIR      *first, *n, **last;
 
@@ -349,7 +372,7 @@ VALUE_PAIR *paircopy2(VALUE_PAIR *vp, int attr, int vendor)
        last = &first;
 
        while (vp) {
-               if ((attr >= 0) &&
+               if ((attr > 0) &&
                    !((vp->attribute == attr) && (vp->vendor == vendor))) {
                        vp = vp->next;
                        continue;
@@ -370,7 +393,7 @@ VALUE_PAIR *paircopy2(VALUE_PAIR *vp, int attr, int vendor)
  */
 VALUE_PAIR *paircopy(VALUE_PAIR *vp)
 {
-       return paircopy2(vp, -1, 0);
+       return paircopy2(vp, 0, 0);
 }
 
 
@@ -598,7 +621,7 @@ void pairmove(VALUE_PAIR **to, VALUE_PAIR **from)
 /*
  *     Move one kind of attributes from one list to the other
  */
-void pairmove2(VALUE_PAIR **to, VALUE_PAIR **from, int attr, int vendor)
+void pairmove2(VALUE_PAIR **to, VALUE_PAIR **from, unsigned int attr, unsigned int vendor)
 {
        VALUE_PAIR *to_tail, *i, *next;
        VALUE_PAIR *iprev = NULL;
@@ -618,25 +641,35 @@ void pairmove2(VALUE_PAIR **to, VALUE_PAIR **from, int attr, int vendor)
 
                /*
                 *      vendor=0, attr = PW_VENDOR_SPECIFIC means
-                *      "match any vendor attribute".  Otherwise, do
-                *      an exact match
+                *      "match any vendor attribute".
                 */
-               if (((vendor != 0) || (attr != PW_VENDOR_SPECIFIC)) &&
-                   (i->attribute != attr) && (i->vendor != vendor)) {
+               if ((vendor == 0) && (attr == PW_VENDOR_SPECIFIC)) {
+                       /*
+                        *      It's a VSA: move it over.
+                        */
+                       if (i->vendor != 0) goto move;
+
+                       /*
+                        *      It's Vendor-Specific: move it over.
+                        */
+                       if (i->attribute == attr) goto move;
+
+                       /*
+                        *      It's not a VSA: ignore it.
+                        */
                        iprev = i;
                        continue;
                }
 
                /*
-                *      If the attribute to move IS a VSA, then it ignores
-                *      any non-VSA attribute.
+                *      If it isn't an exact match, ignore it.
                 */
-               if ((vendor == 0) && (attr == PW_VENDOR_SPECIFIC) &&
-                   (i->vendor == 0)) {
+               if (!((i->vendor == vendor) && (i->attribute == attr))) {
                        iprev = i;
                        continue;
                }
 
+       move:
                /*
                 *      Remove the attribute from the "from" list.
                 */
@@ -798,13 +831,11 @@ static int gettime(const char *valstr, time_t *date)
                f[2] = strchr(f[1], ':'); /* find : separator */
                if (f[2]) {
                  *(f[2]++) = '\0';     /* nuke it, and point to SS */
-               } else {
-                 strcpy(f[2], "0");    /* assignment would discard const */
-               }
+                 tm->tm_sec = atoi(f[2]);
+               }                       /* else leave it as zero */
 
                tm->tm_hour = atoi(f[0]);
                tm->tm_min = atoi(f[1]);
-               tm->tm_sec = atoi(f[2]);
        }
 
        /*
@@ -902,6 +933,10 @@ VALUE_PAIR *pairparsevalue(VALUE_PAIR *vp, const char *value)
                                                c = '\'';
                                                cp++;
                                                break;
+                                       case '\\':
+                                               c = '\\';
+                                               cp++;
+                                               break;
                                        case '`':
                                                c = '`';
                                                cp++;
@@ -925,6 +960,7 @@ VALUE_PAIR *pairparsevalue(VALUE_PAIR *vp, const char *value)
                                *p++ = c;
                                length++;
                        }
+                       vp->vp_strvalue[length] = '\0';
                        vp->length = length;
                        break;
 
@@ -1110,12 +1146,21 @@ VALUE_PAIR *pairparsevalue(VALUE_PAIR *vp, const char *value)
                        break;
 
                case PW_TYPE_IPV6ADDR:
-                       if (inet_pton(AF_INET6, value, &vp->vp_ipv6addr) <= 0) {
-                               fr_strerror_printf("failed to parse IPv6 address "
-                                          "string \"%s\"", value);
-                               return NULL;
+                       {
+                               fr_ipaddr_t ipaddr;
+
+                               if (ip_hton(value, AF_INET6, &ipaddr) < 0) {
+                                       char buffer[1024];
+
+                                       strlcpy(buffer, fr_strerror(), sizeof(buffer));
+
+                                       fr_strerror_printf("failed to parse IPv6 address "
+                                                           "string \"%s\": %s", value, buffer);
+                                       return NULL;
+                               }
+                               vp->vp_ipv6addr = ipaddr.ipaddr.ip6addr;
+                               vp->length = 16; /* length of IPv6 address */
                        }
-                       vp->length = 16; /* length of IPv6 address */
                        break;
 
                case PW_TYPE_IPV6PREFIX:
@@ -1273,7 +1318,7 @@ static VALUE_PAIR *pairmake_any(const char *attribute, const char *value,
        if (strncasecmp(p, "Attr-", 5) != 0) {
                if (strncasecmp(p, "Vendor-", 7) == 0) {
                        vendor = (int) strtol(p + 7, &q, 10);
-                       if ((vendor == 0) || (vendor > 65535)) {
+                       if ((vendor == 0) || (vendor > FR_MAX_VENDOR)) {
                                fr_strerror_printf("Invalid vendor value in attribute name \"%s\"", attribute);
                                return NULL;
                        }
@@ -1354,8 +1399,7 @@ static VALUE_PAIR *pairmake_any(const char *attribute, const char *value,
                                if (attr > 65535) goto attr_error;
                                break;
 
-                       case 4: /* Internal limitations! */
-                               if (attr > 65535) goto attr_error;
+                       case 4:
                                break;
 
                        default: