More escaping / unescaping fixes.
[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                 break;
322
323         case PW_TYPE_IPV4_PREFIX:               /* IPv4 and IPv4 Prefix */
324                 switch (b_type) {
325                 case PW_TYPE_IPV4_ADDR:
326                         return value_data_cidr_cmp_op(op, 4, a->ipv4prefix[1],
327                                                     (uint8_t const *) &a->ipv4prefix + 2,
328                                                     32, (uint8_t const *) &b->ipaddr);
329
330                 case PW_TYPE_IPV4_PREFIX:       /* IPv4 Prefix and IPv4 Prefix */
331                         return value_data_cidr_cmp_op(op, 4, a->ipv4prefix[1],
332                                                     (uint8_t const *) &a->ipv4prefix + 2,
333                                                     b->ipv4prefix[1], (uint8_t const *) &b->ipv4prefix + 2);
334
335                 default:
336                         fr_strerror_printf("Cannot compare IPv4 with IPv6 address");
337                         return -1;
338                 }
339                 break;
340
341         case PW_TYPE_IPV6_ADDR:
342                 switch (b_type) {
343                 case PW_TYPE_IPV6_ADDR:         /* IPv6 and IPv6 */
344                         goto cmp;
345
346                 case PW_TYPE_IPV6_PREFIX:       /* IPv6 and IPv6 Preifx */
347                         return value_data_cidr_cmp_op(op, 16, 128, (uint8_t const *) &a->ipv6addr,
348                                                     b->ipv6prefix[1], (uint8_t const *) &b->ipv6prefix + 2);
349                         break;
350
351                 default:
352                         fr_strerror_printf("Cannot compare IPv6 with IPv4 address");
353                         return -1;
354                 }
355                 break;
356
357         case PW_TYPE_IPV6_PREFIX:
358                 switch (b_type) {
359                 case PW_TYPE_IPV6_ADDR:         /* IPv6 Prefix and IPv6 */
360                         return value_data_cidr_cmp_op(op, 16, a->ipv6prefix[1],
361                                                     (uint8_t const *) &a->ipv6prefix + 2,
362                                                     128, (uint8_t const *) &b->ipv6addr);
363
364                 case PW_TYPE_IPV6_PREFIX:       /* IPv6 Prefix and IPv6 */
365                         return value_data_cidr_cmp_op(op, 16, a->ipv6prefix[1],
366                                                     (uint8_t const *) &a->ipv6prefix + 2,
367                                                     b->ipv6prefix[1], (uint8_t const *) &b->ipv6prefix + 2);
368
369                 default:
370                         fr_strerror_printf("Cannot compare IPv6 with IPv4 address");
371                         return -1;
372                 }
373                 break;
374
375         default:
376         cmp:
377                 compare = value_data_cmp(a_type, a, a_len,
378                                          b_type, b, b_len);
379                 if (compare < -1) {     /* comparison error */
380                         return -1;
381                 }
382         }
383
384         /*
385          *      Now do the operator comparison.
386          */
387         switch (op) {
388         case T_OP_CMP_EQ:
389                 return (compare == 0);
390
391         case T_OP_NE:
392                 return (compare != 0);
393
394         case T_OP_LT:
395                 return (compare < 0);
396
397         case T_OP_GT:
398                 return (compare > 0);
399
400         case T_OP_LE:
401                 return (compare <= 0);
402
403         case T_OP_GE:
404                 return (compare >= 0);
405
406         default:
407                 return 0;
408         }
409 }
410
411 static char const hextab[] = "0123456789abcdef";
412
413 /** Convert string value to a value_data_t type
414  *
415  * @param[in] ctx to alloc strings in.
416  * @param[out] dst where to write parsed value.
417  * @param[in,out] src_type of value data to create/type of value created.
418  * @param[in] src_enumv DICT_ATTR with string aliases for integer values.
419  * @param[in] src String to convert. Binary safe for variable length values if len is provided.
420  * @param[in] src_len may be < 0 in which case strlen(len) is used to determine length, else src_len
421  *        should be the length of the string or sub string to parse.
422  * @return length of data written to out or -1 on parse error.
423  */
424 ssize_t value_data_from_str(TALLOC_CTX *ctx, value_data_t *dst,
425                             PW_TYPE *src_type, DICT_ATTR const *src_enumv,
426                             char const *src, ssize_t src_len, char quote)
427 {
428         DICT_VALUE      *dval;
429         size_t          len;
430         ssize_t         ret;
431         char            buffer[256];
432
433         if (!src) return -1;
434
435         len = (src_len < 0) ? strlen(src) : (size_t)src_len;
436
437         /*
438          *      Set size for all fixed length attributes.
439          */
440         ret = dict_attr_sizes[*src_type][1];    /* Max length */
441
442         /*
443          *      It's a variable ret src_type so we just alloc a new buffer
444          *      of size len and copy.
445          */
446         switch (*src_type) {
447         case PW_TYPE_STRING:
448         {
449                 char            *p;
450                 char const      *q;
451                 int             x;
452
453                 dst->strvalue = p = talloc_memdup(ctx, src, len + 1);
454                 p[len] = '\0';
455                 talloc_set_type(p, char);
456
457                 /*
458                  *      No de-quoting.  Just copy the string.
459                  */
460                 if (!quote) {
461                         ret = len;
462                         goto finish;
463                 }
464
465                 /*
466                  *      Do escaping for single quoted strings.  Only
467                  *      single quotes get escaped.  Everything else is
468                  *      left as-is.
469                  */
470                 if (quote == '\'') {
471                         q = p;
472
473                         /*
474                          *      Escape ONLY the quotation character.
475                          *      Everything else is left as-is.
476                          */
477                         while (q < (dst->strvalue + len)) {
478                                 if ((q[0] == '\\') &&
479                                     (q[1] == '\'')) {
480                                         *(p++) = '\'';
481                                         q += 2;
482                                         continue;
483                                 }
484
485                                 /*
486                                  *      Not escaped, just copy it over.
487                                  */
488                                 *(p++) = *(q++);
489                         }
490
491                         *p = '\0';
492                         ret = p - dst->strvalue;
493                         dst->ptr = talloc_realloc(ctx, dst->ptr, char, ret + 1);
494                         goto finish;
495                 }
496
497                 /*
498                  *      It's "string" or `string`, do all standard
499                  *      escaping.
500                  */
501                 q = p;
502                 while (q < (dst->strvalue + len)) {
503                         char c = *q++;
504
505                         if ((c == '\\') && (q >= (dst->strvalue + len))) {
506                                 fr_strerror_printf("Invalid escape at end of string");
507                                 return -1;
508                         }
509
510                         /*
511                          *      Fix up \X -> ... the binary form of it.
512                          */
513                         if (c == '\\') {
514                                 switch (*q) {
515                                 case 'r':
516                                         c = '\r';
517                                         q++;
518                                         break;
519
520                                 case 'n':
521                                         c = '\n';
522                                         q++;
523                                         break;
524
525                                 case 't':
526                                         c = '\t';
527                                         q++;
528                                         break;
529
530                                 case '\\':
531                                         c = '\\';
532                                         q++;
533                                         break;
534
535                                 default:
536                                         /*
537                                          *      \" --> ", but only inside of double quoted strings, etc.
538                                          */
539                                         if (*q == quote) {
540                                                 c = quote;
541                                                 q++;
542                                                 break;
543                                         }
544
545                                         /*
546                                          *      \000 --> binary zero character
547                                          */
548                                         if ((q[0] >= '0') &&
549                                             (q[0] <= '9') &&
550                                             (q[1] >= '0') &&
551                                             (q[1] <= '9') &&
552                                             (q[2] >= '0') &&
553                                             (q[2] <= '9') &&
554                                             (sscanf(q, "%3o", &x) == 1)) {
555                                                 c = x;
556                                                 q += 3;
557                                         }
558
559                                         /*
560                                          *      Else It's not a recognised escape sequence DON'T
561                                          *      consume the backslash. This is identical
562                                          *      behaviour to bash and most other things that
563                                          *      use backslash escaping.
564                                          */
565                                 }
566                         }
567
568                         *p++ = c;
569                 }
570
571                 *p = '\0';
572                 ret = p - dst->strvalue;
573                 dst->ptr = talloc_realloc(ctx, dst->ptr, char, ret + 1);
574         }
575                 goto finish;
576
577         /* raw octets: 0x01020304... */
578         case PW_TYPE_VSA:
579                 if (strcmp(src, "ANY") == 0) {
580                         ret = 0;
581                         goto finish;
582                 } /* else it's hex */
583
584         case PW_TYPE_OCTETS:
585         {
586                 uint8_t *p;
587
588                 /*
589                  *      No 0x prefix, just copy verbatim.
590                  */
591                 if ((len < 2) || (strncasecmp(src, "0x", 2) != 0)) {
592                         dst->octets = talloc_memdup(ctx, (uint8_t const *)src, len);
593                         talloc_set_type(dst->octets, uint8_t);
594                         ret = len;
595                         goto finish;
596                 }
597
598         do_octets:
599                 len -= 2;
600
601                 /*
602                  *      Invalid.
603                  */
604                 if ((len & 0x01) != 0) {
605                         fr_strerror_printf("Length of Hex String is not even, got %zu bytes", ret);
606                         return -1;
607                 }
608
609                 ret = len >> 1;
610                 p = talloc_array(ctx, uint8_t, ret);
611                 if (fr_hex2bin(p, ret, src + 2, len) != (size_t)ret) {
612                         talloc_free(p);
613                         fr_strerror_printf("Invalid hex data");
614                         return -1;
615                 }
616
617                 dst->octets = p;
618         }
619                 goto finish;
620
621         case PW_TYPE_ABINARY:
622 #ifdef WITH_ASCEND_BINARY
623                 if ((len > 1) && (strncasecmp(src, "0x", 2) == 0)) goto do_octets;
624
625                 if (ascend_parse_filter(dst, src, len) < 0 ) {
626                         /* Allow ascend_parse_filter's strerror to bubble up */
627                         return -1;
628                 }
629                 ret = sizeof(dst->filter);
630                 goto finish;
631 #else
632                 /*
633                  *      If Ascend binary is NOT defined,
634                  *      then fall through to raw octets, so that
635                  *      the user can at least make them by hand...
636                  */
637                 goto do_octets;
638 #endif
639
640         /* don't use this! */
641         case PW_TYPE_TLV:
642         {
643                 uint8_t *p;
644
645                 if ((len < 2) || (len & 0x01) || (strncasecmp(src, "0x", 2) != 0)) {
646                         fr_strerror_printf("Invalid TLV specification");
647                         return -1;
648                 }
649                 len -= 2;
650
651                 ret = len >> 1;
652                 p = talloc_array(ctx, uint8_t, ret);
653                 if (!p) {
654                         fr_strerror_printf("No memory");
655                         return -1;
656                 }
657                 if (fr_hex2bin(p, ret, src + 2, len) != (size_t)ret) {
658                         fr_strerror_printf("Invalid hex data in TLV");
659                         return -1;
660                 }
661
662                 dst->tlv = p;
663         }
664                 goto finish;
665
666         case PW_TYPE_IPV4_ADDR:
667         {
668                 fr_ipaddr_t addr;
669
670                 if (fr_pton4(&addr, src, src_len, fr_hostname_lookups, false) < 0) return -1;
671
672                 /*
673                  *      We allow v4 addresses to have a /32 suffix as some databases (PostgreSQL)
674                  *      print them this way.
675                  */
676                 if (addr.prefix != 32) {
677                         fr_strerror_printf("Invalid IPv4 mask length \"/%i\".  Only \"/32\" permitted "
678                                            "for non-prefix types", addr.prefix);
679                         return -1;
680                 }
681
682                 dst->ipaddr.s_addr = addr.ipaddr.ip4addr.s_addr;
683         }
684                 goto finish;
685
686         case PW_TYPE_IPV4_PREFIX:
687         {
688                 fr_ipaddr_t addr;
689
690                 if (fr_pton4(&addr, src, src_len, fr_hostname_lookups, false) < 0) return -1;
691
692                 dst->ipv4prefix[1] = addr.prefix;
693                 memcpy(dst->ipv4prefix + 2, &addr.ipaddr.ip4addr.s_addr, sizeof(dst->ipv4prefix) - 2);
694         }
695                 goto finish;
696
697         case PW_TYPE_IPV6_ADDR:
698         {
699                 fr_ipaddr_t addr;
700
701                 if (fr_pton6(&addr, src, src_len, fr_hostname_lookups, false) < 0) return -1;
702
703                 /*
704                  *      We allow v6 addresses to have a /128 suffix as some databases (PostgreSQL)
705                  *      print them this way.
706                  */
707                 if (addr.prefix != 128) {
708                         fr_strerror_printf("Invalid IPv6 mask length \"/%i\".  Only \"/128\" permitted "
709                                            "for non-prefix types", addr.prefix);
710                         return -1;
711                 }
712
713                 memcpy(&dst->ipv6addr, &addr.ipaddr.ip6addr.s6_addr, sizeof(dst->ipv6addr));
714         }
715                 goto finish;
716
717         case PW_TYPE_IPV6_PREFIX:
718         {
719                 fr_ipaddr_t addr;
720
721                 if (fr_pton6(&addr, src, src_len, fr_hostname_lookups, false) < 0) return -1;
722
723                 dst->ipv6prefix[1] = addr.prefix;
724                 memcpy(dst->ipv6prefix + 2, &addr.ipaddr.ip6addr.s6_addr, sizeof(dst->ipv6prefix) - 2);
725         }
726                 goto finish;
727
728         default:
729                 break;
730         }
731
732         /*
733          *      It's a fixed size src_type, copy to a temporary buffer and
734          *      \0 terminate if insize >= 0.
735          */
736         if (src_len > 0) {
737                 if (len >= sizeof(buffer)) {
738                         fr_strerror_printf("Temporary buffer too small");
739                         return -1;
740                 }
741
742                 memcpy(buffer, src, src_len);
743                 buffer[src_len] = '\0';
744                 src = buffer;
745         }
746
747         switch (*src_type) {
748         case PW_TYPE_BYTE:
749         {
750                 char *p;
751                 unsigned int i;
752
753                 /*
754                  *      Note that ALL integers are unsigned!
755                  */
756                 i = fr_strtoul(src, &p);
757
758                 /*
759                  *      Look for the named src for the given
760                  *      attribute.
761                  */
762                 if (src_enumv && *p && !is_whitespace(p)) {
763                         if ((dval = dict_valbyname(src_enumv->attr, src_enumv->vendor, src)) == NULL) {
764                                 fr_strerror_printf("Unknown or invalid value \"%s\" for attribute '%s'",
765                                                    src, src_enumv->name);
766                                 return -1;
767                         }
768
769                         dst->byte = dval->value;
770                 } else {
771                         if (i > 255) {
772                                 fr_strerror_printf("Byte value \"%s\" is larger than 255", src);
773                                 return -1;
774                         }
775
776                         dst->byte = i;
777                 }
778                 break;
779         }
780
781         case PW_TYPE_SHORT:
782         {
783                 char *p;
784                 unsigned int i;
785
786                 /*
787                  *      Note that ALL integers are unsigned!
788                  */
789                 i = fr_strtoul(src, &p);
790
791                 /*
792                  *      Look for the named src for the given
793                  *      attribute.
794                  */
795                 if (src_enumv && *p && !is_whitespace(p)) {
796                         if ((dval = dict_valbyname(src_enumv->attr, src_enumv->vendor, src)) == NULL) {
797                                 fr_strerror_printf("Unknown or invalid value \"%s\" for attribute '%s'",
798                                                    src, src_enumv->name);
799                                 return -1;
800                         }
801
802                         dst->ushort = dval->value;
803                 } else {
804                         if (i > 65535) {
805                                 fr_strerror_printf("Short value \"%s\" is larger than 65535", src);
806                                 return -1;
807                         }
808
809                         dst->ushort = i;
810                 }
811                 break;
812         }
813
814         case PW_TYPE_INTEGER:
815         {
816                 char *p;
817                 unsigned int i;
818
819                 /*
820                  *      Note that ALL integers are unsigned!
821                  */
822                 i = fr_strtoul(src, &p);
823
824                 /*
825                  *      Look for the named src for the given
826                  *      attribute.
827                  */
828                 if (src_enumv && *p && !is_whitespace(p)) {
829                         if ((dval = dict_valbyname(src_enumv->attr, src_enumv->vendor, src)) == NULL) {
830                                 fr_strerror_printf("Unknown or invalid value \"%s\" for attribute \"%s\"",
831                                                    src, src_enumv->name);
832                                 return -1;
833                         }
834
835                         dst->integer = dval->value;
836                 } else {
837                         /*
838                          *      Value is always within the limits
839                          */
840                         dst->integer = i;
841                 }
842         }
843                 break;
844
845         case PW_TYPE_INTEGER64:
846         {
847                 uint64_t i;
848
849                 /*
850                  *      Note that ALL integers are unsigned!
851                  */
852                 if (sscanf(src, "%" PRIu64, &i) != 1) {
853                         fr_strerror_printf("Failed parsing \"%s\" as unsigned 64bit integer", src);
854                         return -1;
855                 }
856                 dst->integer64 = i;
857         }
858                 break;
859
860         case PW_TYPE_DATE:
861         {
862                 /*
863                  *      time_t may be 64 bits, whule vp_date MUST be 32-bits.  We need an
864                  *      intermediary variable to handle the conversions.
865                  */
866                 time_t date;
867
868                 if (fr_get_time(src, &date) < 0) {
869                         fr_strerror_printf("failed to parse time string \"%s\"", src);
870                         return -1;
871                 }
872
873                 dst->date = date;
874         }
875
876                 break;
877
878         case PW_TYPE_IFID:
879                 if (ifid_aton(src, (void *) &dst->ifid) == NULL) {
880                         fr_strerror_printf("Failed to parse interface-id string \"%s\"", src);
881                         return -1;
882                 }
883                 break;
884
885         case PW_TYPE_ETHERNET:
886         {
887                 char const *c1, *c2, *cp;
888                 size_t p_len = 0;
889
890                 /*
891                  *      Convert things which are obviously integers to Ethernet addresses
892                  *
893                  *      We assume the number is the bigendian representation of the
894                  *      ethernet address.
895                  */
896                 if (is_integer(src)) {
897                         uint64_t integer = htonll(atoll(src));
898
899                         memcpy(&dst->ether, &integer, sizeof(dst->ether));
900                         break;
901                 }
902
903                 cp = src;
904                 while (*cp) {
905                         if (cp[1] == ':') {
906                                 c1 = hextab;
907                                 c2 = memchr(hextab, tolower((int) cp[0]), 16);
908                                 cp += 2;
909                         } else if ((cp[1] != '\0') && ((cp[2] == ':') || (cp[2] == '\0'))) {
910                                 c1 = memchr(hextab, tolower((int) cp[0]), 16);
911                                 c2 = memchr(hextab, tolower((int) cp[1]), 16);
912                                 cp += 2;
913                                 if (*cp == ':') cp++;
914                         } else {
915                                 c1 = c2 = NULL;
916                         }
917                         if (!c1 || !c2 || (p_len >= sizeof(dst->ether))) {
918                                 fr_strerror_printf("failed to parse Ethernet address \"%s\"", src);
919                                 return -1;
920                         }
921                         dst->ether[p_len] = ((c1-hextab)<<4) + (c2-hextab);
922                         p_len++;
923                 }
924         }
925                 break;
926
927         /*
928          *      Crazy polymorphic (IPv4/IPv6) attribute src_type for WiMAX.
929          *
930          *      We try and make is saner by replacing the original
931          *      da, with either an IPv4 or IPv6 da src_type.
932          *
933          *      These are not dynamic da, and will have the same vendor
934          *      and attribute as the original.
935          */
936         case PW_TYPE_COMBO_IP_ADDR:
937         {
938                 if (inet_pton(AF_INET6, src, &dst->ipv6addr) > 0) {
939                         *src_type = PW_TYPE_IPV6_ADDR;
940                         ret = dict_attr_sizes[PW_TYPE_COMBO_IP_ADDR][1]; /* size of IPv6 address */
941                 } else {
942                         fr_ipaddr_t ipaddr;
943
944                         if (ip_hton(&ipaddr, AF_INET, src, false) < 0) {
945                                 fr_strerror_printf("Failed to find IPv4 address for %s", src);
946                                 return -1;
947                         }
948
949                         *src_type = PW_TYPE_IPV4_ADDR;
950                         dst->ipaddr.s_addr = ipaddr.ipaddr.ip4addr.s_addr;
951                         ret = dict_attr_sizes[PW_TYPE_COMBO_IP_ADDR][0]; /* size of IPv4 address */
952                 }
953         }
954                 break;
955
956         case PW_TYPE_SIGNED:
957                 /* Damned code for 1 WiMAX attribute */
958                 dst->sinteger = (int32_t)strtol(src, NULL, 10);
959                 break;
960
961                 /*
962                  *  Anything else.
963                  */
964         default:
965                 fr_strerror_printf("Unknown attribute type %d", *src_type);
966                 return -1;
967         }
968
969 finish:
970         return ret;
971 }
972
973 /** Performs byte order reversal for types that need it
974  *
975  */
976 static void value_data_hton(value_data_t *dst, PW_TYPE type, void const *src, size_t src_len)
977 {
978         /* 8 byte integers */
979         switch (type) {
980         case PW_TYPE_INTEGER64:
981                 dst->integer64 = htonll(*(uint64_t const *)src);
982                 break;
983
984         /* 4 byte integers */
985         case PW_TYPE_INTEGER:
986         case PW_TYPE_DATE:
987         case PW_TYPE_SIGNED:
988                 dst->integer = htonl(*(uint32_t const *)src);
989                 break;
990
991         /* 2 byte integers */
992         case PW_TYPE_SHORT:
993                 dst->ushort = htons(*(uint16_t const *)src);
994                 break;
995
996         case PW_TYPE_OCTETS:
997         case PW_TYPE_STRING:
998                 fr_assert(0);
999
1000         default:
1001                 memcpy(dst, src, src_len);
1002         }
1003 }
1004
1005 /** Convert one type of value_data_t to another
1006  *
1007  * @note This should be the canonical function used to convert between data types.
1008  *
1009  * @param ctx to allocate buffers in (usually the same as dst)
1010  * @param dst Where to write result of casting.
1011  * @param dst_type to cast to.
1012  * @param dst_enumv Enumerated values used to converts strings to integers.
1013  * @param src_type to cast from.
1014  * @param src_enumv Enumerated values used to convert integers to strings.
1015  * @param src Input data.
1016  * @param src_len Input data len.
1017  * @return the length of data in the dst.
1018  */
1019 ssize_t value_data_cast(TALLOC_CTX *ctx, value_data_t *dst,
1020                         PW_TYPE dst_type, DICT_ATTR const *dst_enumv,
1021                         PW_TYPE src_type, DICT_ATTR const *src_enumv,
1022                         value_data_t const *src, size_t src_len)
1023 {
1024         if (!fr_assert(dst_type != src_type)) return -1;
1025
1026         /*
1027          *      Deserialise a value_data_t
1028          */
1029         if (src_type == PW_TYPE_STRING) {
1030                 return value_data_from_str(ctx, dst, &dst_type, dst_enumv, src->strvalue, src_len, '\0');
1031         }
1032
1033         /*
1034          *      Converts the src data to octets with no processing.
1035          */
1036         if (dst_type == PW_TYPE_OCTETS) {
1037                 if (src_type == PW_TYPE_STRING) {
1038                         dst->octets = talloc_memdup(ctx, src->strvalue, src_len);
1039                 } else {
1040                         value_data_hton(dst, src_type, src, src_len);
1041                         dst->octets = talloc_memdup(ctx, dst, src_len);
1042                 }
1043                 talloc_set_type(dst->octets, uint8_t);
1044                 return talloc_array_length(dst->strvalue);
1045         }
1046
1047         /*
1048          *      Serialise a value_data_t
1049          */
1050         if (dst_type == PW_TYPE_STRING) {
1051                 dst->strvalue = vp_data_aprints_value(ctx, src_type, src_enumv, src, src_len, '\0');
1052                 return talloc_array_length(dst->strvalue) - 1;
1053         }
1054
1055         if ((src_type == PW_TYPE_IFID) &&
1056             (dst_type == PW_TYPE_INTEGER64)) {
1057                 memcpy(&dst->integer64, &src->ifid, sizeof(src->ifid));
1058                 dst->integer64 = htonll(dst->integer64);
1059         fixed_length:
1060                 return dict_attr_sizes[dst_type][0];
1061         }
1062
1063         if ((src_type == PW_TYPE_INTEGER64) &&
1064             (dst_type == PW_TYPE_ETHERNET)) {
1065                 uint8_t array[8];
1066                 uint64_t i;
1067
1068                 i = htonll(src->integer64);
1069                 memcpy(array, &i, 8);
1070
1071                 /*
1072                  *      For OUIs in the DB.
1073                  */
1074                 if ((array[0] != 0) || (array[1] != 0)) return -1;
1075
1076                 memcpy(&dst->ether, &array[2], 6);
1077                 goto fixed_length;
1078         }
1079
1080         /*
1081          *      For integers, we allow the casting of a SMALL type to
1082          *      a larger type, but not vice-versa.
1083          */
1084         if (dst_type == PW_TYPE_INTEGER64) {
1085                 switch (src_type) {
1086                 case PW_TYPE_BYTE:
1087                         dst->integer64 = src->byte;
1088                         break;
1089
1090                 case PW_TYPE_SHORT:
1091                         dst->integer64 = src->ushort;
1092                         break;
1093
1094                 case PW_TYPE_INTEGER:
1095                         dst->integer64 = src->integer;
1096                         break;
1097
1098                 case PW_TYPE_OCTETS:
1099                         goto do_octets;
1100
1101                 default:
1102                 invalid_cast:
1103                         fr_strerror_printf("Invalid cast from %s to %s",
1104                                            fr_int2str(dict_attr_types, src_type, "<INVALID>"),
1105                                            fr_int2str(dict_attr_types, dst_type, "<INVALID>"));
1106                         return -1;
1107
1108                 }
1109                 goto fixed_length;
1110         }
1111
1112         /*
1113          *      We can cast LONG integers to SHORTER ones, so long
1114          *      as the long one is on the LHS.
1115          */
1116         if (dst_type == PW_TYPE_INTEGER) {
1117                 switch (src_type) {
1118                 case PW_TYPE_BYTE:
1119                         dst->integer = src->byte;
1120                         break;
1121
1122                 case PW_TYPE_SHORT:
1123                         dst->integer = src->ushort;
1124                         break;
1125
1126                 case PW_TYPE_OCTETS:
1127                         goto do_octets;
1128
1129                 default:
1130                         goto invalid_cast;
1131                 }
1132                 goto fixed_length;
1133         }
1134
1135         if (dst_type == PW_TYPE_SHORT) {
1136                 switch (src_type) {
1137                 case PW_TYPE_BYTE:
1138                         dst->ushort = src->byte;
1139                         break;
1140
1141                 case PW_TYPE_OCTETS:
1142                         goto do_octets;
1143
1144                 default:
1145                         goto invalid_cast;
1146                 }
1147                 goto fixed_length;
1148         }
1149
1150         /*
1151          *      The attribute we've found has to have a size which is
1152          *      compatible with the type of the destination cast.
1153          */
1154         if ((src_len < dict_attr_sizes[dst_type][0]) ||
1155             (src_len > dict_attr_sizes[dst_type][1])) {
1156                 char const *src_type_name;
1157
1158                 src_type_name =  fr_int2str(dict_attr_types, src_type, "<INVALID>");
1159                 fr_strerror_printf("Invalid cast from %s to %s. Length should be between %zu and %zu but is %zu",
1160                                    src_type_name,
1161                                    fr_int2str(dict_attr_types, dst_type, "<INVALID>"),
1162                                    dict_attr_sizes[dst_type][0], dict_attr_sizes[dst_type][1],
1163                                    src_len);
1164                 return -1;
1165         }
1166
1167         if (src_type == PW_TYPE_OCTETS) {
1168         do_octets:
1169                 value_data_hton(dst, dst_type, src->octets, src_len);
1170                 return src_len;
1171         }
1172
1173         /*
1174          *      Convert host order to network byte order.
1175          */
1176         if ((dst_type == PW_TYPE_IPV4_ADDR) &&
1177             ((src_type == PW_TYPE_INTEGER) ||
1178              (src_type == PW_TYPE_DATE) ||
1179              (src_type == PW_TYPE_SIGNED))) {
1180                 dst->ipaddr.s_addr = htonl(src->integer);
1181
1182         } else if ((src_type == PW_TYPE_IPV4_ADDR) &&
1183                    ((dst_type == PW_TYPE_INTEGER) ||
1184                     (dst_type == PW_TYPE_DATE) ||
1185                     (dst_type == PW_TYPE_SIGNED))) {
1186                 dst->integer = htonl(src->ipaddr.s_addr);
1187
1188         } else {                /* they're of the same byte order */
1189                 memcpy(&dst, &src, src_len);
1190         }
1191
1192         return src_len;
1193 }
1194
1195