Turn on super pedantic warnings in CLANG
[freeradius.git] / src / lib / value.c
1 /*
2  * valuepair.c  Functions to handle value_data_t
3  *
4  * Version:     $Id$
5  *
6  *   This library is free software; you can redistribute it and/or
7  *   modify it under the terms of the GNU Lesser General Public
8  *   License as published by the Free Software Foundation; either
9  *   version 2.1 of the License, or (at your option) any later version.
10  *
11  *   This library is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  *   Lesser General Public License for more details.
15  *
16  *   You should have received a copy of the GNU Lesser General Public
17  *   License along with this library; if not, write to the Free Software
18  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2014 The FreeRADIUS server project
21  */
22
23 RCSID("$Id$")
24
25 #include <freeradius-devel/libradius.h>
26 #include <ctype.h>
27
28 /** Compare two values
29  *
30  * @param[in] a_type of data to compare.
31  * @param[in] a_len of data to compare.
32  * @param[in] a Value to compare.
33  * @param[in] b_type of data to compare.
34  * @param[in] b_len of data to compare.
35  * @param[in] b Value to compare.
36  * @return -1 if a is less than b, 0 if both are equal, 1 if a is more than b, < -1 on error.
37  */
38 int value_data_cmp(PW_TYPE a_type, value_data_t const *a, size_t a_len,
39                    PW_TYPE b_type, value_data_t const *b, size_t b_len)
40 {
41         int compare = 0;
42
43         if (a_type != b_type) {
44                 fr_strerror_printf("Can't compare values of different types");
45                 return -2;
46         }
47
48         /*
49          *      After doing the previous check for special comparisons,
50          *      do the per-type comparison here.
51          */
52         switch (a_type) {
53         case PW_TYPE_ABINARY:
54         case PW_TYPE_OCTETS:
55         case PW_TYPE_STRING:    /* We use memcmp to be \0 safe */
56         {
57                 size_t length;
58
59                 if (a_len > b_len) {
60                         length = a_len;
61                 } else {
62                         length = b_len;
63                 }
64
65                 if (length) {
66                         compare = memcmp(a->octets, b->octets, length);
67                         if (compare != 0) break;
68                 }
69
70                 /*
71                  *      Contents are the same.  The return code
72                  *      is therefore the difference in lengths.
73                  *
74                  *      i.e. "0x00" is smaller than "0x0000"
75                  */
76                 compare = a_len - b_len;
77         }
78                 break;
79
80                 /*
81                  *      Short-hand for simplicity.
82                  */
83 #define CHECK(_type) if (a->_type < b->_type)   { compare = -1; \
84                 } else if (a->_type > b->_type) { compare = +1; }
85
86         case PW_TYPE_BOOLEAN:   /* this isn't a RADIUS type, and shouldn't really ever be used */
87         case PW_TYPE_BYTE:
88                 CHECK(byte);
89                 break;
90
91
92         case PW_TYPE_SHORT:
93                 CHECK(ushort);
94                 break;
95
96         case PW_TYPE_DATE:
97                 CHECK(date);
98                 break;
99
100         case PW_TYPE_INTEGER:
101                 CHECK(integer);
102                 break;
103
104         case PW_TYPE_SIGNED:
105                 CHECK(sinteger);
106                 break;
107
108         case PW_TYPE_INTEGER64:
109                 CHECK(integer64);
110                 break;
111
112         case PW_TYPE_ETHERNET:
113                 compare = memcmp(a->ether, b->ether, sizeof(a->ether));
114                 break;
115
116         case PW_TYPE_IPV4_ADDR: {
117                         uint32_t a_int, b_int;
118
119                         a_int = ntohl(a->ipaddr.s_addr);
120                         b_int = ntohl(b->ipaddr.s_addr);
121                         if (a_int < b_int) {
122                                 compare = -1;
123                         } else if (a_int > b_int) {
124                                 compare = +1;
125                         }
126                 }
127                 break;
128
129         case PW_TYPE_IPV6_ADDR:
130                 compare = memcmp(&a->ipv6addr, &b->ipv6addr, sizeof(a->ipv6addr));
131                 break;
132
133         case PW_TYPE_IPV6_PREFIX:
134                 compare = memcmp(a->ipv6prefix, b->ipv6prefix, sizeof(a->ipv6prefix));
135                 break;
136
137         case PW_TYPE_IPV4_PREFIX:
138                 compare = memcmp(a->ipv4prefix, b->ipv4prefix, sizeof(a->ipv4prefix));
139                 break;
140
141         case PW_TYPE_IFID:
142                 compare = memcmp(a->ifid, b->ifid, sizeof(a->ifid));
143                 break;
144
145         /*
146          *      Na of the types below should be in the REQUEST
147          */
148         case PW_TYPE_INVALID:           /* We should never see these */
149         case PW_TYPE_COMBO_IP_ADDR:             /* This should have been converted into IPADDR/IPV6ADDR */
150         case PW_TYPE_COMBO_IP_PREFIX:           /* This should have been converted into IPADDR/IPV6ADDR */
151         case PW_TYPE_TLV:
152         case PW_TYPE_EXTENDED:
153         case PW_TYPE_LONG_EXTENDED:
154         case PW_TYPE_EVS:
155         case PW_TYPE_VSA:
156         case PW_TYPE_TIMEVAL:
157         case PW_TYPE_MAX:
158                 fr_assert(0);   /* unknown type */
159                 return -2;
160
161         /*
162          *      Do NOT add a default here, as new types are added
163          *      static analysis will warn us they're not handled
164          */
165         }
166
167         if (compare > 0) {
168                 return 1;
169         } else if (compare < 0) {
170                 return -1;
171         }
172         return 0;
173 }
174
175 /*
176  *      We leverage the fact that IPv4 and IPv6 prefixes both
177  *      have the same format:
178  *
179  *      reserved, prefix-len, data...
180  */
181 static int value_data_cidr_cmp_op(FR_TOKEN op, int bytes,
182                                   uint8_t a_net, uint8_t const *a,
183                                   uint8_t b_net, uint8_t const *b)
184 {
185         int i, common;
186         uint32_t mask;
187
188         /*
189          *      Handle the case of netmasks being identical.
190          */
191         if (a_net == b_net) {
192                 int compare;
193
194                 compare = memcmp(a, b, bytes);
195
196                 /*
197                  *      If they're identical return true for
198                  *      identical.
199                  */
200                 if ((compare == 0) &&
201                     ((op == T_OP_CMP_EQ) ||
202                      (op == T_OP_LE) ||
203                      (op == T_OP_GE))) {
204                         return true;
205                 }
206
207                 /*
208                  *      Everything else returns false.
209                  *
210                  *      10/8 == 24/8  --> false
211                  *      10/8 <= 24/8  --> false
212                  *      10/8 >= 24/8  --> false
213                  */
214                 return false;
215         }
216
217         /*
218          *      Netmasks are different.  That limits the
219          *      possible results, based on the operator.
220          */
221         switch (op) {
222         case T_OP_CMP_EQ:
223                 return false;
224
225         case T_OP_NE:
226                 return true;
227
228         case T_OP_LE:
229         case T_OP_LT:   /* 192/8 < 192.168/16 --> false */
230                 if (a_net < b_net) {
231                         return false;
232                 }
233                 break;
234
235         case T_OP_GE:
236         case T_OP_GT:   /* 192/16 > 192.168/8 --> false */
237                 if (a_net > b_net) {
238                         return false;
239                 }
240                 break;
241
242         default:
243                 return false;
244         }
245
246         if (a_net < b_net) {
247                 common = a_net;
248         } else {
249                 common = b_net;
250         }
251
252         /*
253          *      Do the check byte by byte.  If the bytes are
254          *      identical, it MAY be a match.  If they're different,
255          *      it is NOT a match.
256          */
257         i = 0;
258         while (i < bytes) {
259                 /*
260                  *      All leading bytes are identical.
261                  */
262                 if (common == 0) return true;
263
264                 /*
265                  *      Doing bitmasks takes more work.
266                  */
267                 if (common < 8) break;
268
269                 if (a[i] != b[i]) return false;
270
271                 common -= 8;
272                 i++;
273                 continue;
274         }
275
276         mask = 1;
277         mask <<= (8 - common);
278         mask--;
279         mask = ~mask;
280
281         if ((a[i] & mask) == ((b[i] & mask))) {
282                 return true;
283         }
284
285         return false;
286 }
287
288 /** Compare two attributes using an operator
289  *
290  * @param[in] op to use in comparison.
291  * @param[in] a_type of data to compare.
292  * @param[in] a_len of data to compare.
293  * @param[in] a Value to compare.
294  * @param[in] b_type of data to compare.
295  * @param[in] b_len of data to compare.
296  * @param[in] b Value to compare.
297  * @return 1 if true, 0 if false, -1 on error.
298  */
299 int value_data_cmp_op(FR_TOKEN op,
300                       PW_TYPE a_type, value_data_t const *a, size_t a_len,
301                       PW_TYPE b_type, value_data_t const *b, size_t b_len)
302 {
303         int compare = 0;
304
305         if (!a || !b) return -1;
306
307         switch (a_type) {
308         case PW_TYPE_IPV4_ADDR:
309                 switch (b_type) {
310                 case PW_TYPE_IPV4_ADDR:         /* IPv4 and IPv4 */
311                         goto cmp;
312
313                 case PW_TYPE_IPV4_PREFIX:       /* IPv4 and IPv4 Prefix */
314                         return value_data_cidr_cmp_op(op, 4, 32, (uint8_t const *) &a->ipaddr,
315                                                       b->ipv4prefix[1], (uint8_t const *) &b->ipv4prefix[2]);
316
317                 default:
318                         fr_strerror_printf("Cannot compare IPv4 with IPv6 address");
319                         return -1;
320                 }
321
322         case PW_TYPE_IPV4_PREFIX:               /* IPv4 and IPv4 Prefix */
323                 switch (b_type) {
324                 case PW_TYPE_IPV4_ADDR:
325                         return value_data_cidr_cmp_op(op, 4, a->ipv4prefix[1],
326                                                     (uint8_t const *) &a->ipv4prefix[2],
327                                                     32, (uint8_t const *) &b->ipaddr);
328
329                 case PW_TYPE_IPV4_PREFIX:       /* IPv4 Prefix and IPv4 Prefix */
330                         return value_data_cidr_cmp_op(op, 4, a->ipv4prefix[1],
331                                                     (uint8_t const *) &a->ipv4prefix[2],
332                                                     b->ipv4prefix[1], (uint8_t const *) &b->ipv4prefix[2]);
333
334                 default:
335                         fr_strerror_printf("Cannot compare IPv4 with IPv6 address");
336                         return -1;
337                 }
338
339         case PW_TYPE_IPV6_ADDR:
340                 switch (b_type) {
341                 case PW_TYPE_IPV6_ADDR:         /* IPv6 and IPv6 */
342                         goto cmp;
343
344                 case PW_TYPE_IPV6_PREFIX:       /* IPv6 and IPv6 Preifx */
345                         return value_data_cidr_cmp_op(op, 16, 128, (uint8_t const *) &a->ipv6addr,
346                                                       b->ipv6prefix[1], (uint8_t const *) &b->ipv6prefix[2]);
347
348                 default:
349                         fr_strerror_printf("Cannot compare IPv6 with IPv4 address");
350                         return -1;
351                 }
352
353         case PW_TYPE_IPV6_PREFIX:
354                 switch (b_type) {
355                 case PW_TYPE_IPV6_ADDR:         /* IPv6 Prefix and IPv6 */
356                         return value_data_cidr_cmp_op(op, 16, a->ipv6prefix[1],
357                                                       (uint8_t const *) &a->ipv6prefix[2],
358                                                       128, (uint8_t const *) &b->ipv6addr);
359
360                 case PW_TYPE_IPV6_PREFIX:       /* IPv6 Prefix and IPv6 */
361                         return value_data_cidr_cmp_op(op, 16, a->ipv6prefix[1],
362                                                       (uint8_t const *) &a->ipv6prefix[2],
363                                                       b->ipv6prefix[1], (uint8_t const *) &b->ipv6prefix[2]);
364
365                 default:
366                         fr_strerror_printf("Cannot compare IPv6 with IPv4 address");
367                         return -1;
368                 }
369
370         default:
371         cmp:
372                 compare = value_data_cmp(a_type, a, a_len,
373                                          b_type, b, b_len);
374                 if (compare < -1) {     /* comparison error */
375                         return -1;
376                 }
377         }
378
379         /*
380          *      Now do the operator comparison.
381          */
382         switch (op) {
383         case T_OP_CMP_EQ:
384                 return (compare == 0);
385
386         case T_OP_NE:
387                 return (compare != 0);
388
389         case T_OP_LT:
390                 return (compare < 0);
391
392         case T_OP_GT:
393                 return (compare > 0);
394
395         case T_OP_LE:
396                 return (compare <= 0);
397
398         case T_OP_GE:
399                 return (compare >= 0);
400
401         default:
402                 return 0;
403         }
404 }
405
406 static char const hextab[] = "0123456789abcdef";
407
408 /** Convert string value to a value_data_t type
409  *
410  * @param[in] ctx to alloc strings in.
411  * @param[out] dst where to write parsed value.
412  * @param[in,out] src_type of value data to create/type of value created.
413  * @param[in] src_enumv DICT_ATTR with string aliases for integer values.
414  * @param[in] src String to convert. Binary safe for variable length values if len is provided.
415  * @param[in] src_len may be < 0 in which case strlen(len) is used to determine length, else src_len
416  *        should be the length of the string or sub string to parse.
417  * @param[in] quote quotation character used to drive de-escaping
418  * @return length of data written to out or -1 on parse error.
419  */
420 ssize_t value_data_from_str(TALLOC_CTX *ctx, value_data_t *dst,
421                             PW_TYPE *src_type, DICT_ATTR const *src_enumv,
422                             char const *src, ssize_t src_len, char quote)
423 {
424         DICT_VALUE      *dval;
425         size_t          len;
426         ssize_t         ret;
427         char            buffer[256];
428
429         if (!src) return -1;
430
431         len = (src_len < 0) ? strlen(src) : (size_t)src_len;
432
433         /*
434          *      Set size for all fixed length attributes.
435          */
436         ret = dict_attr_sizes[*src_type][1];    /* Max length */
437
438         /*
439          *      It's a variable ret src_type so we just alloc a new buffer
440          *      of size len and copy.
441          */
442         switch (*src_type) {
443         case PW_TYPE_STRING:
444         {
445                 char            *p;
446                 char const      *q;
447                 int             x;
448
449                 dst->strvalue = p = talloc_memdup(ctx, src, len + 1);
450                 p[len] = '\0';
451                 talloc_set_type(p, char);
452
453                 /*
454                  *      No de-quoting.  Just copy the string.
455                  */
456                 if (!quote) {
457                         ret = len;
458                         goto finish;
459                 }
460
461                 /*
462                  *      Do escaping for single quoted strings.  Only
463                  *      single quotes get escaped.  Everything else is
464                  *      left as-is.
465                  */
466                 if (quote == '\'') {
467                         q = p;
468
469                         /*
470                          *      Escape ONLY the quotation character.
471                          *      Everything else is left as-is.
472                          */
473                         while (q < (dst->strvalue + len)) {
474                                 if ((q[0] == '\\') &&
475                                     (q[1] == '\'')) {
476                                         *(p++) = '\'';
477                                         q += 2;
478                                         continue;
479                                 }
480
481                                 /*
482                                  *      Not escaped, just copy it over.
483                                  */
484                                 *(p++) = *(q++);
485                         }
486
487                         *p = '\0';
488                         ret = p - dst->strvalue;
489                         dst->ptr = talloc_realloc(ctx, dst->ptr, char, ret + 1);
490                         goto finish;
491                 }
492
493                 /*
494                  *      It's "string" or `string`, do all standard
495                  *      escaping.
496                  */
497                 q = p;
498                 while (q < (dst->strvalue + len)) {
499                         char c = *q++;
500
501                         if ((c == '\\') && (q >= (dst->strvalue + len))) {
502                                 fr_strerror_printf("Invalid escape at end of string");
503                                 return -1;
504                         }
505
506                         /*
507                          *      Fix up \X -> ... the binary form of it.
508                          */
509                         if (c == '\\') {
510                                 switch (*q) {
511                                 case 'r':
512                                         c = '\r';
513                                         q++;
514                                         break;
515
516                                 case 'n':
517                                         c = '\n';
518                                         q++;
519                                         break;
520
521                                 case 't':
522                                         c = '\t';
523                                         q++;
524                                         break;
525
526                                 case '\\':
527                                         c = '\\';
528                                         q++;
529                                         break;
530
531                                 default:
532                                         /*
533                                          *      \" --> ", but only inside of double quoted strings, etc.
534                                          */
535                                         if (*q == quote) {
536                                                 c = quote;
537                                                 q++;
538                                                 break;
539                                         }
540
541                                         /*
542                                          *      \000 --> binary zero character
543                                          */
544                                         if ((q[0] >= '0') &&
545                                             (q[0] <= '9') &&
546                                             (q[1] >= '0') &&
547                                             (q[1] <= '9') &&
548                                             (q[2] >= '0') &&
549                                             (q[2] <= '9') &&
550                                             (sscanf(q, "%3o", &x) == 1)) {
551                                                 c = x;
552                                                 q += 3;
553                                         }
554
555                                         /*
556                                          *      Else It's not a recognised escape sequence DON'T
557                                          *      consume the backslash. This is identical
558                                          *      behaviour to bash and most other things that
559                                          *      use backslash escaping.
560                                          */
561                                 }
562                         }
563
564                         *p++ = c;
565                 }
566
567                 *p = '\0';
568                 ret = p - dst->strvalue;
569                 dst->ptr = talloc_realloc(ctx, dst->ptr, char, ret + 1);
570         }
571                 goto finish;
572
573         /* raw octets: 0x01020304... */
574         case PW_TYPE_VSA:
575                 if (strcmp(src, "ANY") == 0) {
576                         ret = 0;
577                         goto finish;
578                 } /* else it's hex */
579
580         case PW_TYPE_OCTETS:
581         {
582                 uint8_t *p;
583
584                 /*
585                  *      No 0x prefix, just copy verbatim.
586                  */
587                 if ((len < 2) || (strncasecmp(src, "0x", 2) != 0)) {
588                         dst->octets = talloc_memdup(ctx, (uint8_t const *)src, len);
589                         talloc_set_type(dst->octets, uint8_t);
590                         ret = len;
591                         goto finish;
592                 }
593
594         do_octets:
595                 len -= 2;
596
597                 /*
598                  *      Invalid.
599                  */
600                 if ((len & 0x01) != 0) {
601                         fr_strerror_printf("Length of Hex String is not even, got %zu bytes", ret);
602                         return -1;
603                 }
604
605                 ret = len >> 1;
606                 p = talloc_array(ctx, uint8_t, ret);
607                 if (fr_hex2bin(p, ret, src + 2, len) != (size_t)ret) {
608                         talloc_free(p);
609                         fr_strerror_printf("Invalid hex data");
610                         return -1;
611                 }
612
613                 dst->octets = p;
614         }
615                 goto finish;
616
617         case PW_TYPE_ABINARY:
618 #ifdef WITH_ASCEND_BINARY
619                 if ((len > 1) && (strncasecmp(src, "0x", 2) == 0)) goto do_octets;
620
621                 if (ascend_parse_filter(dst, src, len) < 0 ) {
622                         /* Allow ascend_parse_filter's strerror to bubble up */
623                         return -1;
624                 }
625                 ret = sizeof(dst->filter);
626                 goto finish;
627 #else
628                 /*
629                  *      If Ascend binary is NOT defined,
630                  *      then fall through to raw octets, so that
631                  *      the user can at least make them by hand...
632                  */
633                 goto do_octets;
634 #endif
635
636         /* don't use this! */
637         case PW_TYPE_TLV:
638         {
639                 uint8_t *p;
640
641                 if ((len < 2) || (len & 0x01) || (strncasecmp(src, "0x", 2) != 0)) {
642                         fr_strerror_printf("Invalid TLV specification");
643                         return -1;
644                 }
645                 len -= 2;
646
647                 ret = len >> 1;
648                 p = talloc_array(ctx, uint8_t, ret);
649                 if (!p) {
650                         fr_strerror_printf("No memory");
651                         return -1;
652                 }
653                 if (fr_hex2bin(p, ret, src + 2, len) != (size_t)ret) {
654                         fr_strerror_printf("Invalid hex data in TLV");
655                         return -1;
656                 }
657
658                 dst->tlv = p;
659         }
660                 goto finish;
661
662         case PW_TYPE_IPV4_ADDR:
663         {
664                 fr_ipaddr_t addr;
665
666                 if (fr_pton4(&addr, src, src_len, fr_hostname_lookups, false) < 0) return -1;
667
668                 /*
669                  *      We allow v4 addresses to have a /32 suffix as some databases (PostgreSQL)
670                  *      print them this way.
671                  */
672                 if (addr.prefix != 32) {
673                         fr_strerror_printf("Invalid IPv4 mask length \"/%i\".  Only \"/32\" permitted "
674                                            "for non-prefix types", addr.prefix);
675                         return -1;
676                 }
677
678                 dst->ipaddr.s_addr = addr.ipaddr.ip4addr.s_addr;
679         }
680                 goto finish;
681
682         case PW_TYPE_IPV4_PREFIX:
683         {
684                 fr_ipaddr_t addr;
685
686                 if (fr_pton4(&addr, src, src_len, fr_hostname_lookups, false) < 0) return -1;
687
688                 dst->ipv4prefix[1] = addr.prefix;
689                 memcpy(&dst->ipv4prefix[2], &addr.ipaddr.ip4addr.s_addr, sizeof(dst->ipv4prefix) - 2);
690         }
691                 goto finish;
692
693         case PW_TYPE_IPV6_ADDR:
694         {
695                 fr_ipaddr_t addr;
696
697                 if (fr_pton6(&addr, src, src_len, fr_hostname_lookups, false) < 0) return -1;
698
699                 /*
700                  *      We allow v6 addresses to have a /128 suffix as some databases (PostgreSQL)
701                  *      print them this way.
702                  */
703                 if (addr.prefix != 128) {
704                         fr_strerror_printf("Invalid IPv6 mask length \"/%i\".  Only \"/128\" permitted "
705                                            "for non-prefix types", addr.prefix);
706                         return -1;
707                 }
708
709                 memcpy(&dst->ipv6addr, addr.ipaddr.ip6addr.s6_addr, sizeof(dst->ipv6addr));
710         }
711                 goto finish;
712
713         case PW_TYPE_IPV6_PREFIX:
714         {
715                 fr_ipaddr_t addr;
716
717                 if (fr_pton6(&addr, src, src_len, fr_hostname_lookups, false) < 0) return -1;
718
719                 dst->ipv6prefix[1] = addr.prefix;
720                 memcpy(&dst->ipv6prefix[2], addr.ipaddr.ip6addr.s6_addr, sizeof(dst->ipv6prefix) - 2);
721         }
722                 goto finish;
723
724         default:
725                 break;
726         }
727
728         /*
729          *      It's a fixed size src_type, copy to a temporary buffer and
730          *      \0 terminate if insize >= 0.
731          */
732         if (src_len > 0) {
733                 if (len >= sizeof(buffer)) {
734                         fr_strerror_printf("Temporary buffer too small");
735                         return -1;
736                 }
737
738                 memcpy(buffer, src, src_len);
739                 buffer[src_len] = '\0';
740                 src = buffer;
741         }
742
743         switch (*src_type) {
744         case PW_TYPE_BYTE:
745         {
746                 char *p;
747                 unsigned int i;
748
749                 /*
750                  *      Note that ALL integers are unsigned!
751                  */
752                 i = fr_strtoul(src, &p);
753
754                 /*
755                  *      Look for the named src for the given
756                  *      attribute.
757                  */
758                 if (src_enumv && *p && !is_whitespace(p)) {
759                         if ((dval = dict_valbyname(src_enumv->attr, src_enumv->vendor, src)) == NULL) {
760                                 fr_strerror_printf("Unknown or invalid value \"%s\" for attribute '%s'",
761                                                    src, src_enumv->name);
762                                 return -1;
763                         }
764
765                         dst->byte = dval->value;
766                 } else {
767                         if (i > 255) {
768                                 fr_strerror_printf("Byte value \"%s\" is larger than 255", src);
769                                 return -1;
770                         }
771
772                         dst->byte = i;
773                 }
774                 break;
775         }
776
777         case PW_TYPE_SHORT:
778         {
779                 char *p;
780                 unsigned int i;
781
782                 /*
783                  *      Note that ALL integers are unsigned!
784                  */
785                 i = fr_strtoul(src, &p);
786
787                 /*
788                  *      Look for the named src for the given
789                  *      attribute.
790                  */
791                 if (src_enumv && *p && !is_whitespace(p)) {
792                         if ((dval = dict_valbyname(src_enumv->attr, src_enumv->vendor, src)) == NULL) {
793                                 fr_strerror_printf("Unknown or invalid value \"%s\" for attribute '%s'",
794                                                    src, src_enumv->name);
795                                 return -1;
796                         }
797
798                         dst->ushort = dval->value;
799                 } else {
800                         if (i > 65535) {
801                                 fr_strerror_printf("Short value \"%s\" is larger than 65535", src);
802                                 return -1;
803                         }
804
805                         dst->ushort = i;
806                 }
807                 break;
808         }
809
810         case PW_TYPE_INTEGER:
811         {
812                 char *p;
813                 unsigned int i;
814
815                 /*
816                  *      Note that ALL integers are unsigned!
817                  */
818                 i = fr_strtoul(src, &p);
819
820                 /*
821                  *      Look for the named src for the given
822                  *      attribute.
823                  */
824                 if (src_enumv && *p && !is_whitespace(p)) {
825                         if ((dval = dict_valbyname(src_enumv->attr, src_enumv->vendor, src)) == NULL) {
826                                 fr_strerror_printf("Unknown or invalid value \"%s\" for attribute \"%s\"",
827                                                    src, src_enumv->name);
828                                 return -1;
829                         }
830
831                         dst->integer = dval->value;
832                 } else {
833                         /*
834                          *      Value is always within the limits
835                          */
836                         dst->integer = i;
837                 }
838         }
839                 break;
840
841         case PW_TYPE_INTEGER64:
842         {
843                 uint64_t i;
844
845                 /*
846                  *      Note that ALL integers are unsigned!
847                  */
848                 if (sscanf(src, "%" PRIu64, &i) != 1) {
849                         fr_strerror_printf("Failed parsing \"%s\" as unsigned 64bit integer", src);
850                         return -1;
851                 }
852                 dst->integer64 = i;
853         }
854                 break;
855
856         case PW_TYPE_DATE:
857         {
858                 /*
859                  *      time_t may be 64 bits, whule vp_date MUST be 32-bits.  We need an
860                  *      intermediary variable to handle the conversions.
861                  */
862                 time_t date;
863
864                 if (fr_get_time(src, &date) < 0) {
865                         fr_strerror_printf("failed to parse time string \"%s\"", src);
866                         return -1;
867                 }
868
869                 dst->date = date;
870         }
871
872                 break;
873
874         case PW_TYPE_IFID:
875                 if (ifid_aton(src, (void *) dst->ifid) == NULL) {
876                         fr_strerror_printf("Failed to parse interface-id string \"%s\"", src);
877                         return -1;
878                 }
879                 break;
880
881         case PW_TYPE_ETHERNET:
882         {
883                 char const *c1, *c2, *cp;
884                 size_t p_len = 0;
885
886                 /*
887                  *      Convert things which are obviously integers to Ethernet addresses
888                  *
889                  *      We assume the number is the bigendian representation of the
890                  *      ethernet address.
891                  */
892                 if (is_integer(src)) {
893                         uint64_t integer = htonll(atoll(src));
894
895                         memcpy(dst->ether, &integer, sizeof(dst->ether));
896                         break;
897                 }
898
899                 cp = src;
900                 while (*cp) {
901                         if (cp[1] == ':') {
902                                 c1 = hextab;
903                                 c2 = memchr(hextab, tolower((int) cp[0]), 16);
904                                 cp += 2;
905                         } else if ((cp[1] != '\0') && ((cp[2] == ':') || (cp[2] == '\0'))) {
906                                 c1 = memchr(hextab, tolower((int) cp[0]), 16);
907                                 c2 = memchr(hextab, tolower((int) cp[1]), 16);
908                                 cp += 2;
909                                 if (*cp == ':') cp++;
910                         } else {
911                                 c1 = c2 = NULL;
912                         }
913                         if (!c1 || !c2 || (p_len >= sizeof(dst->ether))) {
914                                 fr_strerror_printf("failed to parse Ethernet address \"%s\"", src);
915                                 return -1;
916                         }
917                         dst->ether[p_len] = ((c1-hextab)<<4) + (c2-hextab);
918                         p_len++;
919                 }
920         }
921                 break;
922
923         /*
924          *      Crazy polymorphic (IPv4/IPv6) attribute src_type for WiMAX.
925          *
926          *      We try and make is saner by replacing the original
927          *      da, with either an IPv4 or IPv6 da src_type.
928          *
929          *      These are not dynamic da, and will have the same vendor
930          *      and attribute as the original.
931          */
932         case PW_TYPE_COMBO_IP_ADDR:
933         {
934                 if (inet_pton(AF_INET6, src, &dst->ipv6addr) > 0) {
935                         *src_type = PW_TYPE_IPV6_ADDR;
936                         ret = dict_attr_sizes[PW_TYPE_COMBO_IP_ADDR][1]; /* size of IPv6 address */
937                 } else {
938                         fr_ipaddr_t ipaddr;
939
940                         if (ip_hton(&ipaddr, AF_INET, src, false) < 0) {
941                                 fr_strerror_printf("Failed to find IPv4 address for %s", src);
942                                 return -1;
943                         }
944
945                         *src_type = PW_TYPE_IPV4_ADDR;
946                         dst->ipaddr.s_addr = ipaddr.ipaddr.ip4addr.s_addr;
947                         ret = dict_attr_sizes[PW_TYPE_COMBO_IP_ADDR][0]; /* size of IPv4 address */
948                 }
949         }
950                 break;
951
952         case PW_TYPE_SIGNED:
953                 /* Damned code for 1 WiMAX attribute */
954                 dst->sinteger = (int32_t)strtol(src, NULL, 10);
955                 break;
956
957                 /*
958                  *  Anything else.
959                  */
960         default:
961                 fr_strerror_printf("Unknown attribute type %d", *src_type);
962                 return -1;
963         }
964
965 finish:
966         return ret;
967 }
968
969 /** Performs byte order reversal for types that need it
970  *
971  */
972 static void value_data_hton(value_data_t *dst, PW_TYPE type, void const *src, size_t src_len)
973 {
974         /* 8 byte integers */
975         switch (type) {
976         case PW_TYPE_INTEGER64:
977                 dst->integer64 = htonll(*(uint64_t const *)src);
978                 break;
979
980         /* 4 byte integers */
981         case PW_TYPE_INTEGER:
982         case PW_TYPE_DATE:
983         case PW_TYPE_SIGNED:
984                 dst->integer = htonl(*(uint32_t const *)src);
985                 break;
986
987         /* 2 byte integers */
988         case PW_TYPE_SHORT:
989                 dst->ushort = htons(*(uint16_t const *)src);
990                 break;
991
992         case PW_TYPE_OCTETS:
993         case PW_TYPE_STRING:
994                 fr_assert(0);
995                 return;         /* shouldn't happen */
996
997         default:
998                 memcpy(dst, src, src_len);
999         }
1000 }
1001
1002 /** Convert one type of value_data_t to another
1003  *
1004  * @note This should be the canonical function used to convert between data types.
1005  *
1006  * @param ctx to allocate buffers in (usually the same as dst)
1007  * @param dst Where to write result of casting.
1008  * @param dst_type to cast to.
1009  * @param dst_enumv Enumerated values used to converts strings to integers.
1010  * @param src_type to cast from.
1011  * @param src_enumv Enumerated values used to convert integers to strings.
1012  * @param src Input data.
1013  * @param src_len Input data len.
1014  * @return the length of data in the dst or -1 on error.
1015  */
1016 ssize_t value_data_cast(TALLOC_CTX *ctx, value_data_t *dst,
1017                         PW_TYPE dst_type, DICT_ATTR const *dst_enumv,
1018                         PW_TYPE src_type, DICT_ATTR const *src_enumv,
1019                         value_data_t const *src, size_t src_len)
1020 {
1021         if (!fr_assert(dst_type != src_type)) return -1;
1022
1023         /*
1024          *      Deserialise a value_data_t
1025          */
1026         if (src_type == PW_TYPE_STRING) {
1027                 return value_data_from_str(ctx, dst, &dst_type, dst_enumv, src->strvalue, src_len, '\0');
1028         }
1029
1030         /*
1031          *      Converts the src data to octets with no processing.
1032          */
1033         if (dst_type == PW_TYPE_OCTETS) {
1034                 value_data_hton(dst, src_type, src, src_len);
1035                 dst->octets = talloc_memdup(ctx, dst, src_len);
1036                 talloc_set_type(dst->octets, uint8_t);
1037                 return talloc_array_length(dst->strvalue);
1038         }
1039
1040         /*
1041          *      Serialise a value_data_t
1042          */
1043         if (dst_type == PW_TYPE_STRING) {
1044                 dst->strvalue = vp_data_aprints_value(ctx, src_type, src_enumv, src, src_len, '\0');
1045                 return talloc_array_length(dst->strvalue) - 1;
1046         }
1047
1048         if ((src_type == PW_TYPE_IFID) &&
1049             (dst_type == PW_TYPE_INTEGER64)) {
1050                 memcpy(&dst->integer64, src->ifid, sizeof(src->ifid));
1051                 dst->integer64 = htonll(dst->integer64);
1052         fixed_length:
1053                 return dict_attr_sizes[dst_type][0];
1054         }
1055
1056         if ((src_type == PW_TYPE_INTEGER64) &&
1057             (dst_type == PW_TYPE_ETHERNET)) {
1058                 uint8_t array[8];
1059                 uint64_t i;
1060
1061                 i = htonll(src->integer64);
1062                 memcpy(array, &i, 8);
1063
1064                 /*
1065                  *      For OUIs in the DB.
1066                  */
1067                 if ((array[0] != 0) || (array[1] != 0)) return -1;
1068
1069                 memcpy(dst->ether, &array[2], 6);
1070                 goto fixed_length;
1071         }
1072
1073         /*
1074          *      For integers, we allow the casting of a SMALL type to
1075          *      a larger type, but not vice-versa.
1076          */
1077         if (dst_type == PW_TYPE_INTEGER64) {
1078                 switch (src_type) {
1079                 case PW_TYPE_BYTE:
1080                         dst->integer64 = src->byte;
1081                         break;
1082
1083                 case PW_TYPE_SHORT:
1084                         dst->integer64 = src->ushort;
1085                         break;
1086
1087                 case PW_TYPE_INTEGER:
1088                         dst->integer64 = src->integer;
1089                         break;
1090
1091                 case PW_TYPE_OCTETS:
1092                         goto do_octets;
1093
1094                 default:
1095                 invalid_cast:
1096                         fr_strerror_printf("Invalid cast from %s to %s",
1097                                            fr_int2str(dict_attr_types, src_type, "<INVALID>"),
1098                                            fr_int2str(dict_attr_types, dst_type, "<INVALID>"));
1099                         return -1;
1100
1101                 }
1102                 goto fixed_length;
1103         }
1104
1105         /*
1106          *      We can cast LONG integers to SHORTER ones, so long
1107          *      as the long one is on the LHS.
1108          */
1109         if (dst_type == PW_TYPE_INTEGER) {
1110                 switch (src_type) {
1111                 case PW_TYPE_BYTE:
1112                         dst->integer = src->byte;
1113                         break;
1114
1115                 case PW_TYPE_SHORT:
1116                         dst->integer = src->ushort;
1117                         break;
1118
1119                 case PW_TYPE_OCTETS:
1120                         goto do_octets;
1121
1122                 default:
1123                         goto invalid_cast;
1124                 }
1125                 goto fixed_length;
1126         }
1127
1128         if (dst_type == PW_TYPE_SHORT) {
1129                 switch (src_type) {
1130                 case PW_TYPE_BYTE:
1131                         dst->ushort = src->byte;
1132                         break;
1133
1134                 case PW_TYPE_OCTETS:
1135                         goto do_octets;
1136
1137                 default:
1138                         goto invalid_cast;
1139                 }
1140                 goto fixed_length;
1141         }
1142
1143         /*
1144          *      Conversions between IPv4 addresses, IPv6 addresses, IPv4 prefixes and IPv6 prefixes
1145          *
1146          *      For prefix to ipaddress conversions, we assume that the host portion has already
1147          *      been zeroed out.
1148          *
1149          *      We allow casts from v6 to v4 if the v6 address has the correct mapping prefix.
1150          *
1151          *      We only allow casts from prefixes to addresses if the prefix is the the length of
1152          *      the address, e.g. 32 for ipv4 128 for ipv6.
1153          */
1154         {
1155                 /*
1156                  *      10 bytes of 0x00 2 bytes of 0xff
1157                  */
1158                 static uint8_t const v4_v6_map[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1159                                                      0x00, 0x00, 0x00, 0x00, 0xff, 0xff };
1160
1161                 switch (dst_type) {
1162                 case PW_TYPE_IPV4_ADDR:
1163                         switch (src_type) {
1164                         case PW_TYPE_IPV6_ADDR:
1165                                 if (memcmp(src->ipv6addr.s6_addr, v4_v6_map, sizeof(v4_v6_map)) != 0) {
1166                                 bad_v6_prefix_map:
1167                                         fr_strerror_printf("Invalid cast from %s to %s.  No IPv4-IPv6 mapping prefix",
1168                                                            fr_int2str(dict_attr_types, src_type, "<INVALID>"),
1169                                                            fr_int2str(dict_attr_types, dst_type, "<INVALID>"));
1170                                         return -1;
1171                                 }
1172
1173                                 memcpy(&dst->ipaddr, &src->ipv6addr.s6_addr[sizeof(v4_v6_map)],
1174                                        sizeof(dst->ipaddr));
1175                                 goto fixed_length;
1176
1177                         case PW_TYPE_IPV4_PREFIX:
1178                                 if (src->ipv4prefix[1] != 32) {
1179                                 bad_v4_prefix_len:
1180                                         fr_strerror_printf("Invalid cast from %s to %s.  Only /32 prefixes may be "
1181                                                            "cast to IP address types",
1182                                                            fr_int2str(dict_attr_types, src_type, "<INVALID>"),
1183                                                            fr_int2str(dict_attr_types, dst_type, "<INVALID>"));
1184                                         return -1;
1185                                 }
1186
1187                                 memcpy(&dst->ipaddr, &src->ipv4prefix[2], sizeof(dst->ipaddr));
1188                                 goto fixed_length;
1189
1190                         case PW_TYPE_IPV6_PREFIX:
1191                                 if (src->ipv6prefix[1] != 128) {
1192                                 bad_v6_prefix_len:
1193                                         fr_strerror_printf("Invalid cast from %s to %s.  Only /128 prefixes may be "
1194                                                            "cast to IP address types",
1195                                                            fr_int2str(dict_attr_types, src_type, "<INVALID>"),
1196                                                            fr_int2str(dict_attr_types, dst_type, "<INVALID>"));
1197                                         return -1;
1198                                 }
1199                                 if (memcmp(&src->ipv6prefix[2], v4_v6_map, sizeof(v4_v6_map)) != 0) {
1200                                         goto bad_v6_prefix_map;
1201                                 }
1202                                 memcpy(&dst->ipaddr, &src->ipv6prefix[2 + sizeof(v4_v6_map)],
1203                                        sizeof(dst->ipaddr));
1204                                 goto fixed_length;
1205
1206                         default:
1207                                 break;
1208                         }
1209                         break;
1210
1211                 case PW_TYPE_IPV6_ADDR:
1212                         switch (src_type) {
1213                         case PW_TYPE_IPV4_ADDR:
1214                                 /* Add the v4/v6 mapping prefix */
1215                                 memcpy(dst->ipv6addr.s6_addr, v4_v6_map, sizeof(v4_v6_map));
1216                                 memcpy(&dst->ipv6addr.s6_addr[sizeof(v4_v6_map)], &src->ipaddr,
1217                                        sizeof(dst->ipv6addr.s6_addr) - sizeof(v4_v6_map));
1218
1219                                 goto fixed_length;
1220
1221                         case PW_TYPE_IPV4_PREFIX:
1222                                 if (src->ipv4prefix[1] != 32) goto bad_v4_prefix_len;
1223
1224                                 /* Add the v4/v6 mapping prefix */
1225                                 memcpy(dst->ipv6addr.s6_addr, v4_v6_map, sizeof(v4_v6_map));
1226                                 memcpy(&dst->ipv6addr.s6_addr[sizeof(v4_v6_map)], &src->ipv4prefix[2],
1227                                        sizeof(dst->ipv6addr.s6_addr) - sizeof(v4_v6_map));
1228                                 goto fixed_length;
1229
1230                         case PW_TYPE_IPV6_PREFIX:
1231                                 if (src->ipv4prefix[1] != 128) goto bad_v6_prefix_len;
1232
1233                                 memcpy(dst->ipv6addr.s6_addr, &src->ipv6prefix[2], sizeof(dst->ipv6addr.s6_addr));
1234                                 goto fixed_length;
1235
1236                         default:
1237                                 break;
1238                         }
1239                         break;
1240
1241                 case PW_TYPE_IPV4_PREFIX:
1242                         switch (src_type) {
1243                         case PW_TYPE_IPV4_ADDR:
1244                                 memcpy(&dst->ipv4prefix[2], &src->ipaddr, sizeof(dst->ipv4prefix) - 2);
1245                                 dst->ipv4prefix[0] = 0;
1246                                 dst->ipv4prefix[1] = 32;
1247                                 goto fixed_length;
1248
1249                         case PW_TYPE_IPV6_ADDR:
1250                                 if (memcmp(src->ipv6addr.s6_addr, v4_v6_map, sizeof(v4_v6_map)) != 0) {
1251                                         goto bad_v6_prefix_map;
1252                                 }
1253                                 memcpy(&dst->ipv4prefix[2], &src->ipv6addr.s6_addr[sizeof(v4_v6_map)],
1254                                        sizeof(dst->ipv4prefix) - 2);
1255                                 dst->ipv4prefix[0] = 0;
1256                                 dst->ipv4prefix[1] = 32;
1257                                 goto fixed_length;
1258
1259                         case PW_TYPE_IPV6_PREFIX:
1260                                 if (memcmp(&src->ipv6prefix[2], v4_v6_map, sizeof(v4_v6_map)) != 0) {
1261                                         goto bad_v6_prefix_map;
1262                                 }
1263
1264                                 /*
1265                                  *      Prefix must be >= 96 bits. If it's < 96 bytes and the
1266                                  *      above check passed, the v6 address wasn't masked
1267                                  *      correctly when it was packet into a value_data_t.
1268                                  */
1269                                 if (!fr_assert(src->ipv6prefix[1] >= (sizeof(v4_v6_map) * 8))) return -1;
1270
1271                                 memcpy(&dst->ipv4prefix[2], &src->ipv6prefix[2 + sizeof(v4_v6_map)],
1272                                        sizeof(dst->ipv4prefix) - 2);
1273                                 dst->ipv4prefix[0] = 0;
1274                                 dst->ipv4prefix[1] = src->ipv6prefix[1] - (sizeof(v4_v6_map) * 8);
1275                                 goto fixed_length;
1276
1277                         default:
1278                                 break;
1279                         }
1280                         break;
1281
1282                 case PW_TYPE_IPV6_PREFIX:
1283                         switch (src_type) {
1284                         case PW_TYPE_IPV4_ADDR:
1285                                 /* Add the v4/v6 mapping prefix */
1286                                 memcpy(&dst->ipv6prefix[2], v4_v6_map, sizeof(v4_v6_map));
1287                                 memcpy(&dst->ipv6prefix[2 + sizeof(v4_v6_map)], &src->ipaddr,
1288                                        (sizeof(dst->ipv6prefix) - 2) - sizeof(v4_v6_map));
1289                                 dst->ipv6prefix[0] = 0;
1290                                 dst->ipv6prefix[1] = 128;
1291                                 goto fixed_length;
1292
1293                         case PW_TYPE_IPV4_PREFIX:
1294                                 /* Add the v4/v6 mapping prefix */
1295                                 memcpy(&dst->ipv6prefix[2], v4_v6_map, sizeof(v4_v6_map));
1296                                 memcpy(&dst->ipv6prefix[2 + sizeof(v4_v6_map)], &src->ipv4prefix[2],
1297                                        (sizeof(dst->ipv6prefix) - 2) - sizeof(v4_v6_map));
1298                                 dst->ipv6prefix[0] = 0;
1299                                 dst->ipv6prefix[1] = (sizeof(v4_v6_map) * 8) + src->ipv4prefix[1];
1300                                 goto fixed_length;
1301
1302                         case PW_TYPE_IPV6_ADDR:
1303                                 memcpy(&dst->ipv6prefix[2], &src->ipv6addr, sizeof(dst->ipv6prefix) - 2);
1304                                 dst->ipv6prefix[0] = 0;
1305                                 dst->ipv6prefix[1] = 128;
1306                                 goto fixed_length;
1307
1308                         default:
1309                                 break;
1310                         }
1311
1312                         break;
1313
1314                 default:
1315                         break;
1316                 }
1317         }
1318
1319         /*
1320          *      The attribute we've found has to have a size which is
1321          *      compatible with the type of the destination cast.
1322          */
1323         if ((src_len < dict_attr_sizes[dst_type][0]) ||
1324             (src_len > dict_attr_sizes[dst_type][1])) {
1325                 char const *src_type_name;
1326
1327                 src_type_name =  fr_int2str(dict_attr_types, src_type, "<INVALID>");
1328                 fr_strerror_printf("Invalid cast from %s to %s. Length should be between %zu and %zu but is %zu",
1329                                    src_type_name,
1330                                    fr_int2str(dict_attr_types, dst_type, "<INVALID>"),
1331                                    dict_attr_sizes[dst_type][0], dict_attr_sizes[dst_type][1],
1332                                    src_len);
1333                 return -1;
1334         }
1335
1336         if (src_type == PW_TYPE_OCTETS) {
1337         do_octets:
1338                 value_data_hton(dst, dst_type, src->octets, src_len);
1339                 return src_len;
1340         }
1341
1342         /*
1343          *      Convert host order to network byte order.
1344          */
1345         if ((dst_type == PW_TYPE_IPV4_ADDR) &&
1346             ((src_type == PW_TYPE_INTEGER) ||
1347              (src_type == PW_TYPE_DATE) ||
1348              (src_type == PW_TYPE_SIGNED))) {
1349                 dst->ipaddr.s_addr = htonl(src->integer);
1350
1351         } else if ((src_type == PW_TYPE_IPV4_ADDR) &&
1352                    ((dst_type == PW_TYPE_INTEGER) ||
1353                     (dst_type == PW_TYPE_DATE) ||
1354                     (dst_type == PW_TYPE_SIGNED))) {
1355                 dst->integer = htonl(src->ipaddr.s_addr);
1356
1357         } else {                /* they're of the same byte order */
1358                 memcpy(&dst, &src, src_len);
1359         }
1360
1361         return src_len;
1362 }
1363
1364 /** Copy value data verbatim duplicating any buffers
1365  *
1366  * @param ctx To allocate buffers in.
1367  * @param dst Where to copy value_data to.
1368  * @param src_type Type of src.
1369  * @param src Where to copy value_data from.
1370  * @param src_len Where
1371  */
1372 ssize_t value_data_copy(TALLOC_CTX *ctx, value_data_t *dst, PW_TYPE src_type,
1373                         const value_data_t *src, size_t src_len)
1374 {
1375         switch (src_type) {
1376         default:
1377                 memcpy(dst, src, sizeof(*src));
1378                 break;
1379
1380         case PW_TYPE_STRING:
1381                 dst->strvalue = talloc_memdup(ctx, src->strvalue, src_len + 1);
1382                 if (!dst->strvalue) return -1;
1383                 talloc_set_type(dst->strvalue, char);
1384                 break;
1385
1386         case PW_TYPE_OCTETS:
1387                 dst->octets = talloc_memdup(ctx, src->octets, src_len);
1388                 talloc_set_type(dst->strvalue, uint8_t);
1389                 if (!dst->octets) return -1;
1390                 break;
1391         }
1392
1393         return src_len;
1394 }