time_t may be 64 bits, so we can't pass &vp->vp_date directly
[freeradius.git] / src / lib / valuepair.c
1 /*
2  * valuepair.c  Functions to handle VALUE_PAIRs
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 2000,2006  The FreeRADIUS server project
21  */
22
23 #include <freeradius-devel/ident.h>
24 RCSID("$Id$")
25
26 #include        <freeradius-devel/libradius.h>
27
28 #include        <ctype.h>
29
30 #ifdef HAVE_MALLOC_H
31 #  include      <malloc.h>
32 #endif
33
34 #ifdef HAVE_REGEX_H
35 #  include      <regex.h>
36 #endif
37
38 static const char *months[] = {
39         "jan", "feb", "mar", "apr", "may", "jun",
40         "jul", "aug", "sep", "oct", "nov", "dec" };
41
42 VALUE_PAIR *pairalloc(DICT_ATTR *da)
43 {
44         VALUE_PAIR *vp;
45
46         vp = malloc(sizeof(*vp));
47         if (!vp) return NULL;
48         memset(vp, 0, sizeof(*vp));
49
50         if (da) {
51                 vp->attribute = da->attr;
52                 vp->vendor = da->vendor;
53                 vp->type = da->type;
54                 strlcpy(vp->name, da->name, sizeof(vp->name));
55                 vp->flags = da->flags;
56         } else {
57                 vp->attribute = 0;
58                 vp->vendor = 0;
59                 vp->type = PW_TYPE_OCTETS;
60                 vp->name[0] = '\0';
61                 memset(&vp->flags, 0, sizeof(vp->flags));
62         }
63
64         switch (vp->type) {
65                 case PW_TYPE_BYTE:
66                         vp->length = 1;
67                         break;
68
69                 case PW_TYPE_SHORT:
70                         vp->length = 2;
71                         break;
72
73                 case PW_TYPE_INTEGER:
74                 case PW_TYPE_IPADDR:
75                 case PW_TYPE_DATE:
76                         vp->length = 4;
77                         break;
78
79                 case PW_TYPE_IFID:
80                         vp->length = sizeof(vp->vp_ifid);
81                         break;
82
83                 case PW_TYPE_IPV6ADDR:
84                         vp->length = sizeof(vp->vp_ipv6addr);
85                         break;
86
87                 case PW_TYPE_IPV6PREFIX:
88                         vp->length = sizeof(vp->vp_ipv6prefix);
89                         break;
90
91                 case PW_TYPE_ETHERNET:
92                         vp->length = sizeof(vp->vp_ether);
93                         break;
94
95                 default:
96                         vp->length = 0;
97                         break;
98         }
99
100         return vp;
101 }
102
103
104 /*
105  *      Create a new valuepair.
106  */
107 VALUE_PAIR *paircreate(int attr, int type)
108 {
109         VALUE_PAIR      *vp;
110         DICT_ATTR       *da;
111
112         da = dict_attrbyvalue(attr);
113         if ((vp = pairalloc(da)) == NULL) {
114                 librad_log("out of memory");
115                 return NULL;
116         }
117         vp->operator = T_OP_EQ;
118
119         /*
120          *      Update the name...
121          */
122         if (!da) {
123                 if (VENDOR(attr) == 0) {
124                         sprintf(vp->name, "Attr-%u", attr);
125
126                 } else {
127                         DICT_VENDOR *v;
128
129                         v = dict_vendorbyvalue(VENDOR(attr));
130                         if (v) {
131                                 sprintf(vp->name, "%s-Attr-%u",
132                                         v->name, attr & 0xffff);
133                         } else {
134                                 sprintf(vp->name, "Vendor-%u-Attr-%u",
135                                         VENDOR(attr), attr & 0xffff);
136                         }
137                 }
138                 vp->type = type;
139
140         } else {
141                 vp->type = da->type;
142         }
143
144         return vp;
145 }
146
147 /*
148  *      release the memory used by a single attribute-value pair
149  *      just a wrapper around free() for now.
150  */
151 void pairbasicfree(VALUE_PAIR *pair)
152 {
153         /* clear the memory here */
154         memset(pair, 0, sizeof(*pair));
155         free(pair);
156 }
157
158 /*
159  *      Release the memory used by a list of attribute-value
160  *      pairs, and sets the pair pointer to NULL.
161  */
162 void pairfree(VALUE_PAIR **pair_ptr)
163 {
164         VALUE_PAIR      *next, *pair;
165
166         if (!pair_ptr) return;
167         pair = *pair_ptr;
168
169         while (pair != NULL) {
170                 next = pair->next;
171                 pairbasicfree(pair);
172                 pair = next;
173         }
174
175         *pair_ptr = NULL;
176 }
177
178
179 /*
180  *      Find the pair with the matching attribute
181  */
182 VALUE_PAIR * pairfind(VALUE_PAIR *first, int attr)
183 {
184         while(first && first->attribute != attr)
185                 first = first->next;
186         return first;
187 }
188
189
190 /*
191  *      Delete the pair(s) with the matching attribute
192  */
193 void pairdelete(VALUE_PAIR **first, int attr)
194 {
195         VALUE_PAIR *i, *next;
196         VALUE_PAIR **last = first;
197
198         for(i = *first; i; i = next) {
199                 next = i->next;
200                 if (i->attribute == attr) {
201                         *last = next;
202                         pairbasicfree(i);
203                 } else {
204                         last = &i->next;
205                 }
206         }
207 }
208
209 /*
210  *      Add a pair at the end of a VALUE_PAIR list.
211  */
212 void pairadd(VALUE_PAIR **first, VALUE_PAIR *add)
213 {
214         VALUE_PAIR *i;
215
216         if (!add) return;
217
218         if (*first == NULL) {
219                 *first = add;
220                 return;
221         }
222         for(i = *first; i->next; i = i->next)
223                 ;
224         i->next = add;
225 }
226
227 /*
228  *      Add or replace a pair at the end of a VALUE_PAIR list.
229  */
230 void pairreplace(VALUE_PAIR **first, VALUE_PAIR *replace)
231 {
232         VALUE_PAIR *i, *next;
233         VALUE_PAIR **prev = first;
234
235         if (*first == NULL) {
236                 *first = replace;
237                 return;
238         }
239
240         /*
241          *      Not an empty list, so find item if it is there, and
242          *      replace it. Note, we always replace the first one, and
243          *      we ignore any others that might exist.
244          */
245         for(i = *first; i; i = next) {
246                 next = i->next;
247
248                 /*
249                  *      Found the first attribute, replace it,
250                  *      and return.
251                  */
252                 if (i->attribute == replace->attribute) {
253                         *prev = replace;
254
255                         /*
256                          *      Should really assert that replace->next == NULL
257                          */
258                         replace->next = next;
259                         pairbasicfree(i);
260                         return;
261                 }
262
263                 /*
264                  *      Point to where the attribute should go.
265                  */
266                 prev = &i->next;
267         }
268
269         /*
270          *      If we got here, we didn't find anything to replace, so
271          *      stopped at the last item, which we just append to.
272          */
273         *prev = replace;
274 }
275
276 /*
277  *      Copy just a certain type of pairs.
278  */
279 VALUE_PAIR *paircopy2(VALUE_PAIR *vp, int attr)
280 {
281         VALUE_PAIR      *first, *n, **last;
282
283         first = NULL;
284         last = &first;
285
286         while (vp) {
287                 if (attr >= 0 && vp->attribute != attr) {
288                         vp = vp->next;
289                         continue;
290                 }
291                 if ((n = malloc(sizeof(*n))) == NULL) {
292                         librad_log("out of memory");
293                         return first;
294                 }
295                 memcpy(n, vp, sizeof(VALUE_PAIR));
296                 n->next = NULL;
297                 *last = n;
298                 last = &n->next;
299                 vp = vp->next;
300         }
301         return first;
302 }
303
304
305 /*
306  *      Copy a pairlist.
307  */
308 VALUE_PAIR *paircopy(VALUE_PAIR *vp)
309 {
310         return paircopy2(vp, -1);
311 }
312
313
314 /*
315  *      Move attributes from one list to the other
316  *      if not already present.
317  */
318 void pairmove(VALUE_PAIR **to, VALUE_PAIR **from)
319 {
320         VALUE_PAIR **tailto, *i, *j, *next;
321         VALUE_PAIR *tailfrom = NULL;
322         VALUE_PAIR *found;
323         int has_password = 0;
324
325         /*
326          *      First, see if there are any passwords here, and
327          *      point "tailto" to the end of the "to" list.
328          */
329         tailto = to;
330         for(i = *to; i; i = i->next) {
331                 if (i->attribute == PW_USER_PASSWORD ||
332                     i->attribute == PW_CRYPT_PASSWORD)
333                         has_password = 1;
334                 tailto = &i->next;
335         }
336
337         /*
338          *      Loop over the "from" list.
339          */
340         for(i = *from; i; i = next) {
341                 next = i->next;
342
343                 /*
344                  *      If there was a password in the "to" list,
345                  *      do not move any other password from the
346                  *      "from" to the "to" list.
347                  */
348                 if (has_password &&
349                     (i->attribute == PW_USER_PASSWORD ||
350                      i->attribute == PW_CRYPT_PASSWORD)) {
351                         tailfrom = i;
352                         continue;
353                 }
354
355                 switch (i->operator) {
356                         /*
357                          *      These are COMPARISON attributes
358                          *      from a check list, and are not
359                          *      supposed to be copied!
360                          */
361                         case T_OP_NE:
362                         case T_OP_GE:
363                         case T_OP_GT:
364                         case T_OP_LE:
365                         case T_OP_LT:
366                         case T_OP_CMP_TRUE:
367                         case T_OP_CMP_FALSE:
368                         case T_OP_CMP_EQ:
369                                 tailfrom = i;
370                                 continue;
371
372                         default:
373                                 break;
374                 }
375
376                 /*
377                  *      If the attribute is already present in "to",
378                  *      do not move it from "from" to "to". We make
379                  *      an exception for "Hint" which can appear multiple
380                  *      times, and we never move "Fall-Through".
381                  */
382                 if (i->attribute == PW_FALL_THROUGH ||
383                     (i->attribute != PW_HINT && i->attribute != PW_FRAMED_ROUTE)) {
384
385                         found = pairfind(*to, i->attribute);
386                         switch (i->operator) {
387
388                           /*
389                            *    If matching attributes are found,
390                            *    delete them.
391                            */
392                         case T_OP_SUB:          /* -= */
393                                 if (found) {
394                                         if (!i->vp_strvalue[0] ||
395                                             (strcmp((char *)found->vp_strvalue,
396                                                     (char *)i->vp_strvalue) == 0)){
397                                                 pairdelete(to, found->attribute);
398
399                                                 /*
400                                                  *      'tailto' may have been
401                                                  *      deleted...
402                                                  */
403                                                 tailto = to;
404                                                 for(j = *to; j; j = j->next) {
405                                                         tailto = &j->next;
406                                                 }
407                                         }
408                                 }
409                                 tailfrom = i;
410                                 continue;
411                                 break;
412
413 /* really HAVE_REGEX_H */
414 #if 0
415                                 /*
416                                  *  Attr-Name =~ "s/find/replace/"
417                                  *
418                                  *  Very bad code.  Barely working,
419                                  *  if at all.
420                                  */
421
422                         case T_OP_REG_EQ:
423                           if (found &&
424                               (i->vp_strvalue[0] == 's')) {
425                             regex_t             reg;
426                             regmatch_t          match[1];
427
428                             char *str;
429                             char *p, *q;
430
431                             p = i->vp_strvalue + 1;
432                             q = strchr(p + 1, *p);
433                             if (!q || (q[strlen(q) - 1] != *p)) {
434                               tailfrom = i;
435                               continue;
436                             }
437                             str = strdup(i->vp_strvalue + 2);
438                             q = strchr(str, *p);
439                             *(q++) = '\0';
440                             q[strlen(q) - 1] = '\0';
441
442                             regcomp(&reg, str, 0);
443                             if (regexec(&reg, found->vp_strvalue,
444                                         1, match, 0) == 0) {
445                               fprintf(stderr, "\"%s\" will have %d to %d replaced with %s\n",
446                                       found->vp_strvalue, match[0].rm_so,
447                                       match[0].rm_eo, q);
448
449                             }
450                             regfree(&reg);
451                             free(str);
452                           }
453                           tailfrom = i; /* don't copy it over */
454                           continue;
455                           break;
456 #endif
457                         case T_OP_EQ:           /* = */
458                                 /*
459                                  *  FIXME: Tunnel attributes with
460                                  *  different tags are different
461                                  *  attributes.
462                                  */
463                                 if (found) {
464                                         tailfrom = i;
465                                         continue; /* with the loop */
466                                 }
467                                 break;
468
469                           /*
470                            *  If a similar attribute is found,
471                            *  replace it with the new one.  Otherwise,
472                            *  add the new one to the list.
473                            */
474                         case T_OP_SET:          /* := */
475                                 if (found) {
476                                         VALUE_PAIR *mynext = found->next;
477
478                                         /*
479                                          *      Do NOT call pairdelete()
480                                          *      here, due to issues with
481                                          *      re-writing "request->username".
482                                          *
483                                          *      Everybody calls pairmove,
484                                          *      and expects it to work.
485                                          *      We can't update request->username
486                                          *      here, so instead we over-write
487                                          *      the vp that it's pointing to.
488                                          */
489                                         memcpy(found, i, sizeof(*found));
490                                         found->next = mynext;
491
492                                         pairdelete(&found->next, found->attribute);
493
494                                         /*
495                                          *      'tailto' may have been
496                                          *      deleted...
497                                          */
498                                         for(j = found; j; j = j->next) {
499                                                 tailto = &j->next;
500                                         }
501                                         continue;
502                                 }
503                                 break;
504
505                           /*
506                            *  Add the new element to the list, even
507                            *  if similar ones already exist.
508                            */
509                         default:
510                         case T_OP_ADD: /* += */
511                                 break;
512                         }
513                 }
514                 if (tailfrom)
515                         tailfrom->next = next;
516                 else
517                         *from = next;
518
519                 /*
520                  *      If ALL of the 'to' attributes have been deleted,
521                  *      then ensure that the 'tail' is updated to point
522                  *      to the head.
523                  */
524                 if (!*to) {
525                         tailto = to;
526                 }
527                 *tailto = i;
528                 if (i) {
529                         i->next = NULL;
530                         tailto = &i->next;
531                 }
532         }
533 }
534
535 /*
536  *      Move one kind of attributes from one list to the other
537  */
538 void pairmove2(VALUE_PAIR **to, VALUE_PAIR **from, int attr)
539 {
540         VALUE_PAIR *to_tail, *i, *next;
541         VALUE_PAIR *iprev = NULL;
542
543         /*
544          *      Find the last pair in the "to" list and put it in "to_tail".
545          */
546         if (*to != NULL) {
547                 to_tail = *to;
548                 for(i = *to; i; i = i->next)
549                         to_tail = i;
550         } else
551                 to_tail = NULL;
552
553         for(i = *from; i; i = next) {
554                 next = i->next;
555
556
557                 /*
558                  *      If the attribute to move is NOT a VSA, then it
559                  *      ignores any attributes which do not match exactly.
560                  */
561                 if ((attr != PW_VENDOR_SPECIFIC) &&
562                     (i->attribute != attr)) {
563                         iprev = i;
564                         continue;
565                 }
566
567                 /*
568                  *      If the attribute to move IS a VSA, then it ignores
569                  *      any non-VSA attribute.
570                  */
571                 if ((attr == PW_VENDOR_SPECIFIC) &&
572                     (VENDOR(i->attribute) == 0)) {
573                         iprev = i;
574                         continue;
575                 }
576
577                 /*
578                  *      Remove the attribute from the "from" list.
579                  */
580                 if (iprev)
581                         iprev->next = next;
582                 else
583                         *from = next;
584
585                 /*
586                  *      Add the attribute to the "to" list.
587                  */
588                 if (to_tail)
589                         to_tail->next = i;
590                 else
591                         *to = i;
592                 to_tail = i;
593                 i->next = NULL;
594         }
595 }
596
597
598 /*
599  *      Sort of strtok/strsep function.
600  */
601 static char *mystrtok(char **ptr, const char *sep)
602 {
603         char    *res;
604
605         if (**ptr == 0)
606                 return NULL;
607         while (**ptr && strchr(sep, **ptr))
608                 (*ptr)++;
609         if (**ptr == 0)
610                 return NULL;
611         res = *ptr;
612         while (**ptr && strchr(sep, **ptr) == NULL)
613                 (*ptr)++;
614         if (**ptr != 0)
615                 *(*ptr)++ = 0;
616         return res;
617 }
618
619 /*
620  *      Turn printable string into time_t
621  *      Returns -1 on error, 0 on OK.
622  */
623 static int gettime(const char *valstr, uint32_t *lvalue)
624 {
625         int             i;
626         time_t          t;
627         struct tm       *tm, s_tm;
628         char            buf[64];
629         char            *p;
630         char            *f[4];
631         char            *tail = '\0';
632
633         /*
634          * Test for unix timestamp date
635          */
636         *lvalue = strtoul(valstr, &tail, 10);
637         if (*tail == '\0') {
638                 return 0;
639         }
640
641         tm = &s_tm;
642         memset(tm, 0, sizeof(*tm));
643         tm->tm_isdst = -1;      /* don't know, and don't care about DST */
644
645         strlcpy(buf, valstr, sizeof(buf));
646
647         p = buf;
648         f[0] = mystrtok(&p, " \t");
649         f[1] = mystrtok(&p, " \t");
650         f[2] = mystrtok(&p, " \t");
651         f[3] = mystrtok(&p, " \t"); /* may, or may not, be present */
652         if (!f[0] || !f[1] || !f[2]) return -1;
653
654         /*
655          *      The time has a colon, where nothing else does.
656          *      So if we find it, bubble it to the back of the list.
657          */
658         if (f[3]) {
659                 for (i = 0; i < 3; i++) {
660                         if (strchr(f[i], ':')) {
661                                 p = f[3];
662                                 f[3] = f[i];
663                                 f[i] = p;
664                                 break;
665                         }
666                 }
667         }
668
669         /*
670          *  The month is text, which allows us to find it easily.
671          */
672         tm->tm_mon = 12;
673         for (i = 0; i < 3; i++) {
674                 if (isalpha( (int) *f[i])) {
675                         /*
676                          *  Bubble the month to the front of the list
677                          */
678                         p = f[0];
679                         f[0] = f[i];
680                         f[i] = p;
681
682                         for (i = 0; i < 12; i++) {
683                                 if (strncasecmp(months[i], f[0], 3) == 0) {
684                                         tm->tm_mon = i;
685                                         break;
686                                 }
687                         }
688                 }
689         }
690
691         /* month not found? */
692         if (tm->tm_mon == 12) return -1;
693
694         /*
695          *  The year may be in f[1], or in f[2]
696          */
697         tm->tm_year = atoi(f[1]);
698         tm->tm_mday = atoi(f[2]);
699
700         if (tm->tm_year >= 1900) {
701                 tm->tm_year -= 1900;
702
703         } else {
704                 /*
705                  *  We can't use 2-digit years any more, they make it
706                  *  impossible to tell what's the day, and what's the year.
707                  */
708                 if (tm->tm_mday < 1900) return -1;
709
710                 /*
711                  *  Swap the year and the day.
712                  */
713                 i = tm->tm_year;
714                 tm->tm_year = tm->tm_mday - 1900;
715                 tm->tm_mday = i;
716         }
717
718         /*
719          *  If the day is out of range, die.
720          */
721         if ((tm->tm_mday < 1) || (tm->tm_mday > 31)) {
722                 return -1;
723         }
724
725         /*
726          *      There may be %H:%M:%S.  Parse it in a hacky way.
727          */
728         if (f[3]) {
729                 f[0] = f[3];    /* HH */
730                 f[1] = strchr(f[0], ':'); /* find : separator */
731                 if (!f[1]) return -1;
732
733                 *(f[1]++) = '\0'; /* nuke it, and point to MM:SS */
734
735                 f[2] = strchr(f[1], ':'); /* find : separator */
736                 if (f[2]) {
737                   *(f[2]++) = '\0';     /* nuke it, and point to SS */
738                 } else {
739                   strcpy(f[2], "0");    /* assignment would discard const */
740                 }
741
742                 tm->tm_hour = atoi(f[0]);
743                 tm->tm_min = atoi(f[1]);
744                 tm->tm_sec = atoi(f[2]);
745         }
746
747         /*
748          *  Returns -1 on error.
749          */
750         t = mktime(tm);
751         if (t == (time_t) -1) return -1;
752
753         *lvalue = t;
754
755         return 0;
756 }
757
758 static const char *hextab = "0123456789abcdef";
759
760 /*
761  *  Parse a string value into a given VALUE_PAIR
762  *
763  *  FIXME: we probably want to fix this function to accept
764  *  octets as values for any type of attribute.  We should then
765  *  double-check the parsed value, to be sure it's legal for that
766  *  type (length, etc.)
767  */
768 VALUE_PAIR *pairparsevalue(VALUE_PAIR *vp, const char *value)
769 {
770         char            *p, *s=0;
771         const char      *cp, *cs;
772         int             length, x;
773         DICT_VALUE      *dval;
774
775         /*
776          *      Even for integers, dates and ip addresses we
777          *      keep the original string in vp->vp_strvalue.
778          */
779         strlcpy((char *)vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
780         vp->length = strlen(vp->vp_strvalue);
781
782         switch(vp->type) {
783                 case PW_TYPE_STRING:
784                         /*
785                          *      Do escaping here
786                          */
787                         p = vp->vp_strvalue;
788                         cp = value;
789                         length = 0;
790
791                         while (*cp && (length < sizeof(vp->vp_strvalue))) {
792                                 char c = *cp++;
793
794                                 if (c == '\\') {
795                                         switch (*cp) {
796                                         case 'r':
797                                                 c = '\r';
798                                                 cp++;
799                                                 break;
800                                         case 'n':
801                                                 c = '\n';
802                                                 cp++;
803                                                 break;
804                                         case 't':
805                                                 c = '\t';
806                                                 cp++;
807                                                 break;
808                                         case '"':
809                                                 c = '"';
810                                                 cp++;
811                                                 break;
812                                         case '\'':
813                                                 c = '\'';
814                                                 cp++;
815                                                 break;
816                                         case '`':
817                                                 c = '`';
818                                                 cp++;
819                                                 break;
820                                         case '\0':
821                                                 c = '\\'; /* no cp++ */
822                                                 break;
823                                         default:
824                                                 if ((cp[0] >= '0') &&
825                                                     (cp[0] <= '9') &&
826                                                     (cp[1] >= '0') &&
827                                                     (cp[1] <= '9') &&
828                                                     (cp[2] >= '0') &&
829                                                     (cp[2] <= '9') &&
830                                                     (sscanf(cp, "%3o", &x) == 1)) {
831                                                         c = x;
832                                                         cp += 3;
833                                                 } /* else just do '\\' */
834                                         }
835                                 }
836                                 *p++ = c;
837                                 length++;
838                         }
839                         vp->length = length;
840                         break;
841
842                 case PW_TYPE_IPADDR:
843                         /*
844                          *      It's a comparison, not a real IP.
845                          */
846                         if ((vp->operator == T_OP_REG_EQ) ||
847                             (vp->operator == T_OP_REG_NE)) {
848                                 break;
849                         }
850
851                         /*
852                          *      FIXME: complain if hostname
853                          *      cannot be resolved, or resolve later!
854                          */
855                         if ((p = strrchr(value, '+')) != NULL && !p[1]) {
856                                 cs = s = strdup(value);
857                                 p = strrchr(s, '+');
858                                 *p = 0;
859                                 vp->flags.addport = 1;
860                         } else {
861                                 p = NULL;
862                                 cs = value;
863                         }
864
865                         {
866                                 lrad_ipaddr_t ipaddr;
867
868                                 if (ip_hton(cs, AF_INET, &ipaddr) < 0) {
869                                         librad_log("Failed to find IP address for %s", cs);
870                                         return NULL;
871                                 }
872
873                                 vp->vp_ipaddr = ipaddr.ipaddr.ip4addr.s_addr;
874                         }
875                         if (s) free(s);
876                         vp->length = 4;
877                         break;
878
879                 case PW_TYPE_BYTE:
880                         if ((value[0] == '0') && (value[1] == 'x')) {
881                                 goto do_octets;
882                         }
883
884                         /*
885                          *      Note that ALL integers are unsigned!
886                          */
887                         vp->vp_integer = (uint32_t) strtoul(value, &p, 10);
888                         if (!*p) {
889                                 if (vp->vp_integer > 255) {
890                                         librad_log("Byte value \"%s\" is larger than 255", value);
891                                         return NULL;
892                                 }
893                                 vp->length = 1;
894                                 break;
895                         }
896
897                         /*
898                          *      Look for the named value for the given
899                          *      attribute.
900                          */
901                         if ((dval = dict_valbyname(vp->attribute, value)) == NULL) {
902                                 librad_log("Unknown value %s for attribute %s",
903                                            value, vp->name);
904                                 return NULL;
905                         }
906                         vp->vp_integer = dval->value;
907                         vp->length = 1;
908                         break;
909
910                 case PW_TYPE_SHORT:
911                         /*
912                          *      Note that ALL integers are unsigned!
913                          */
914                         vp->vp_integer = (uint32_t) strtoul(value, &p, 10);
915                         if (!*p) {
916                                 if (vp->vp_integer > 65535) {
917                                         librad_log("Byte value \"%s\" is larger than 65535", value);
918                                         return NULL;
919                                 }
920                                 vp->length = 2;
921                                 break;
922                         }
923
924                         /*
925                          *      Look for the named value for the given
926                          *      attribute.
927                          */
928                         if ((dval = dict_valbyname(vp->attribute, value)) == NULL) {
929                                 librad_log("Unknown value %s for attribute %s",
930                                            value, vp->name);
931                                 return NULL;
932                         }
933                         vp->vp_integer = dval->value;
934                         vp->length = 2;
935                         break;
936
937                 case PW_TYPE_INTEGER:
938                         /*
939                          *      Note that ALL integers are unsigned!
940                          */
941                         vp->vp_integer = (uint32_t) strtoul(value, &p, 10);
942                         if (!*p) {
943                                 vp->length = 4;
944                                 break;
945                         }
946
947                         /*
948                          *      Look for the named value for the given
949                          *      attribute.
950                          */
951                         if ((dval = dict_valbyname(vp->attribute, value)) == NULL) {
952                                 librad_log("Unknown value %s for attribute %s",
953                                            value, vp->name);
954                                 return NULL;
955                         }
956                         vp->vp_integer = dval->value;
957                         vp->length = 4;
958                         break;
959
960                 case PW_TYPE_DATE:
961                         {
962                                 /*
963                                  *      time_t may be 64 bits, whule vp_date
964                                  *      MUST be 32-bits.  We need an
965                                  *      intermediary variable to handle
966                                  *      the conversions.
967                                  */
968                                 time_t date;
969
970                                 if (gettime(value, &date) < 0) {
971                                         librad_log("failed to parse time string "
972                                                    "\"%s\"", value);
973                                         return NULL;
974                                 }
975
976                                 vp->vp_date = date;
977                         }
978                         vp->length = 4;
979                         break;
980
981                 case PW_TYPE_ABINARY:
982 #ifdef ASCEND_BINARY
983                         if (strncasecmp(value, "0x", 2) == 0) {
984                                 vp->type = PW_TYPE_OCTETS;
985                                 goto do_octets;
986                         }
987
988                         if (ascend_parse_filter(vp) < 0 ) {
989                                 librad_log("failed to parse Ascend binary attribute: %s",
990                                            librad_errstr);
991                                 return NULL;
992                         }
993                         break;
994
995                         /*
996                          *      If Ascend binary is NOT defined,
997                          *      then fall through to raw octets, so that
998                          *      the user can at least make them by hand...
999                          */
1000 #endif
1001         do_octets:
1002                         /* raw octets: 0x01020304... */
1003                 case PW_TYPE_OCTETS:
1004                         if (strncasecmp(value, "0x", 2) == 0) {
1005                                 uint8_t *us;
1006                                 cp = value + 2;
1007                                 us = vp->vp_octets;
1008                                 vp->length = 0;
1009
1010
1011                                 /*
1012                                  *      There is only one character,
1013                                  *      die.
1014                                  */
1015                                 if ((strlen(cp) & 0x01) != 0) {
1016                                         librad_log("Hex string is not an even length string.");
1017                                         return NULL;
1018                                 }
1019
1020
1021                                 while (*cp &&
1022                                        (vp->length < MAX_STRING_LEN)) {
1023                                         unsigned int tmp;
1024
1025                                         if (sscanf(cp, "%02x", &tmp) != 1) {
1026                                                 librad_log("Non-hex characters at %c%c", cp[0], cp[1]);
1027                                                 return NULL;
1028                                         }
1029
1030                                         cp += 2;
1031                                         *(us++) = tmp;
1032                                         vp->length++;
1033                                 }
1034                         }
1035                         break;
1036
1037                 case PW_TYPE_IFID:
1038                         if (ifid_aton(value, (unsigned char *) vp->vp_strvalue) == NULL) {
1039                                 librad_log("failed to parse interface-id "
1040                                            "string \"%s\"", value);
1041                                 return NULL;
1042                         }
1043                         vp->length = 8;
1044                         vp->vp_strvalue[vp->length] = '\0';
1045                         break;
1046
1047                 case PW_TYPE_IPV6ADDR:
1048                         if (inet_pton(AF_INET6, value, vp->vp_strvalue) <= 0) {
1049                                 librad_log("failed to parse IPv6 address "
1050                                            "string \"%s\"", value);
1051                                 return NULL;
1052                         }
1053                         vp->length = 16; /* length of IPv6 address */
1054                         vp->vp_strvalue[vp->length] = '\0';
1055                         break;
1056
1057                 case PW_TYPE_IPV6PREFIX:
1058                         p = strchr(value, '/');
1059                         if (!p || ((p - value) >= 256)) {
1060                                 librad_log("invalid IPv6 prefix "
1061                                            "string \"%s\"", value);
1062                                 return NULL;
1063                         } else {
1064                                 unsigned int prefix;
1065                                 char buffer[256], *eptr;
1066
1067                                 memcpy(buffer, value, p - value);
1068                                 buffer[p - value] = '\0';
1069
1070                                 if (inet_pton(AF_INET6, buffer, vp->vp_strvalue + 2) <= 0) {
1071                                         librad_log("failed to parse IPv6 address "
1072                                                    "string \"%s\"", value);
1073                                         return NULL;
1074                                 }
1075
1076                                 prefix = strtoul(p + 1, &eptr, 10);
1077                                 if ((prefix > 128) || *eptr) {
1078                                         librad_log("failed to parse IPv6 address "
1079                                                    "string \"%s\"", value);
1080                                         return NULL;
1081                                 }
1082                                 vp->vp_strvalue[1] = prefix;
1083                         }
1084                         vp->vp_strvalue[0] = '\0';
1085                         vp->length = 16 + 2;
1086                         break;
1087
1088                 case PW_TYPE_ETHERNET:
1089                         {
1090                                 int i = 0;
1091                                 const char *c1, *c2;
1092
1093                                 cp = value;
1094                                 while (*cp) {
1095                                         if (cp[1] == ':') {
1096                                                 c1 = hextab;
1097                                                 c2 = memchr(hextab, tolower((int) cp[0]), 16);
1098                                                 cp += 2;
1099                                         } else if ((cp[1] != '\0') &&
1100                                                    ((cp[2] == ':') ||
1101                                                     (cp[2] == '\0'))) {
1102                                                    c1 = memchr(hextab, tolower((int) cp[0]), 16);
1103                                                    c2 = memchr(hextab, tolower((int) cp[1]), 16);
1104                                                    cp += 2;
1105                                                    if (*cp == ':') cp++;
1106                                         } else {
1107                                                 c1 = c2 = NULL;
1108                                         }
1109                                         if (!c1 || !c2 || (i >= sizeof(vp->vp_ether))) {
1110                                                 librad_log("failed to parse Ethernet address \"%s\"", value);
1111                                                 return NULL;
1112                                         }
1113                                         vp->vp_ether[i] = ((c1-hextab)<<4) + (c2-hextab);
1114                                         i++;
1115                                 }
1116                         }
1117                         vp->length = 6;
1118                         break;
1119
1120                         /*
1121                          *  Anything else.
1122                          */
1123                 default:
1124                         librad_log("unknown attribute type %d", vp->type);
1125                         return NULL;
1126         }
1127
1128         return vp;
1129 }
1130
1131 /*
1132  *      Create a VALUE_PAIR from an ASCII attribute and value,
1133  *      where the attribute name is in the form:
1134  *
1135  *      Attr-%d
1136  *      Vendor-%d-Attr-%d
1137  */
1138 static VALUE_PAIR *pairmake_any(const char *attribute, const char *value,
1139                                 int operator)
1140 {
1141         int             attr;
1142         const char      *p;
1143         VALUE_PAIR      *vp;
1144
1145         /*
1146          *      Unknown attributes MUST be of type 'octets'
1147          */
1148         if (value && (strncasecmp(value, "0x", 2) != 0)) {
1149                 goto error;
1150         }
1151
1152         /*
1153          *      Attr-%d
1154          */
1155         if (strncasecmp(attribute, "Attr-", 5) == 0) {
1156                 attr = atoi(attribute + 5);
1157                 p = attribute + 5;
1158                 p += strspn(p, "0123456789");
1159                 if (*p != 0) goto error;
1160
1161                 /*
1162                  *      Vendor-%d-Attr-%d
1163                  */
1164         } else if (strncasecmp(attribute, "Vendor-", 7) == 0) {
1165                 int vendor;
1166
1167                 vendor = atoi(attribute + 7);
1168                 if ((vendor == 0) || (vendor > 65535)) goto error;
1169
1170                 p = attribute + 7;
1171                 p += strspn(p, "0123456789");
1172
1173                 /*
1174                  *      Not Vendor-%d-Attr-%d
1175                  */
1176                 if (strncasecmp(p, "-Attr-", 6) != 0) goto error;
1177
1178                 p += 6;
1179                 attr = atoi(p);
1180
1181                 p += strspn(p, "0123456789");
1182                 if (*p != 0) goto error;
1183
1184                 if ((attr == 0) || (attr > 65535)) goto error;
1185
1186                 attr |= (vendor << 16);
1187
1188                 /*
1189                  *      VendorName-Attr-%d
1190                  */
1191         } else if (((p = strchr(attribute, '-')) != NULL) &&
1192                    (strncasecmp(p, "-Attr-", 6) == 0)) {
1193                 int vendor;
1194                 char buffer[256];
1195
1196                 if (((size_t) (p - attribute)) >= sizeof(buffer)) goto error;
1197
1198                 memcpy(buffer, attribute, p - attribute);
1199                 buffer[p - attribute] = '\0';
1200
1201                 vendor = dict_vendorbyname(buffer);
1202                 if (vendor == 0) goto error;
1203
1204                 p += 6;
1205                 attr = atoi(p);
1206
1207                 p += strspn(p, "0123456789");
1208                 if (*p != 0) goto error;
1209
1210                 if ((attr == 0) || (attr > 65535)) goto error;
1211
1212                 attr |= (vendor << 16);
1213
1214         } else {                /* very much unknown: die */
1215         error:
1216                 librad_log("Unknown attribute \"%s\"", attribute);
1217                 return NULL;
1218         }
1219
1220         /*
1221          *      We've now parsed the attribute properly, Let's create
1222          *      it.  This next stop also looks the attribute up in the
1223          *      dictionary, and creates the appropriate type for it.
1224          */
1225         if ((vp = paircreate(attr, PW_TYPE_OCTETS)) == NULL) {
1226                 librad_log("out of memory");
1227                 return NULL;
1228         }
1229
1230         if (pairparsevalue(vp, value) == NULL) {
1231                 pairfree(&vp);
1232                 return NULL;
1233         }
1234         vp->operator = (operator == 0) ? T_OP_EQ : operator;
1235
1236         return vp;
1237 }
1238
1239
1240 /*
1241  *      Create a VALUE_PAIR from an ASCII attribute and value.
1242  */
1243 VALUE_PAIR *pairmake(const char *attribute, const char *value, int operator)
1244 {
1245         DICT_ATTR       *da;
1246         VALUE_PAIR      *vp;
1247         char            *tc, *ts;
1248         signed char     tag;
1249         int             found_tag;
1250 #ifdef HAVE_REGEX_H
1251         int             res;
1252         regex_t         cre;
1253 #endif
1254
1255         /*
1256          *    Check for tags in 'Attribute:Tag' format.
1257          */
1258         found_tag = 0;
1259         tag = 0;
1260
1261         ts = strrchr(attribute, ':');
1262         if (ts && !ts[1]) {
1263                 librad_log("Invalid tag for attribute %s", attribute);
1264                 return NULL;
1265         }
1266
1267         if (ts && ts[1]) {
1268                  /* Colon found with something behind it */
1269                  if (ts[1] == '*' && ts[2] == 0) {
1270                          /* Wildcard tag for check items */
1271                          tag = TAG_ANY;
1272                          *ts = 0;
1273                  } else if ((ts[1] >= '0') && (ts[1] <= '9')) {
1274                          /* It's not a wild card tag */
1275                          tag = strtol(ts + 1, &tc, 0);
1276                          if (tc && !*tc && TAG_VALID_ZERO(tag))
1277                                  *ts = 0;
1278                          else tag = 0;
1279                  } else {
1280                          librad_log("Invalid tag for attribute %s", attribute);
1281                          return NULL;
1282                  }
1283                  found_tag = 1;
1284         }
1285
1286         /*
1287          *      It's not found in the dictionary, so we use
1288          *      another method to create the attribute.
1289          */
1290         if ((da = dict_attrbyname(attribute)) == NULL) {
1291                 return pairmake_any(attribute, value, operator);
1292         }
1293
1294         if ((vp = pairalloc(da)) == NULL) {
1295                 librad_log("out of memory");
1296                 return NULL;
1297         }
1298         vp->operator = (operator == 0) ? T_OP_EQ : operator;
1299
1300         /*      Check for a tag in the 'Merit' format of:
1301          *      :Tag:Value.  Print an error if we already found
1302          *      a tag in the Attribute.
1303          */
1304
1305         if (value && (*value == ':' && da->flags.has_tag)) {
1306                 /* If we already found a tag, this is invalid */
1307                 if(found_tag) {
1308                         pairbasicfree(vp);
1309                         librad_log("Duplicate tag %s for attribute %s",
1310                                    value, vp->name);
1311                         DEBUG("Duplicate tag %s for attribute %s\n",
1312                                    value, vp->name);
1313                         return NULL;
1314
1315                 }
1316                 /* Colon found and attribute allows a tag */
1317                 if (value[1] == '*' && value[2] == ':') {
1318                        /* Wildcard tag for check items */
1319                        tag = TAG_ANY;
1320                        value += 3;
1321                 } else {
1322                        /* Real tag */
1323                        tag = strtol(value + 1, &tc, 0);
1324                        if (tc && *tc==':' && TAG_VALID_ZERO(tag))
1325                             value = tc + 1;
1326                        else tag = 0;
1327                 }
1328                 found_tag = 1;
1329         }
1330
1331         if (found_tag) {
1332           vp->flags.tag = tag;
1333         }
1334
1335         switch (vp->operator) {
1336         default:
1337                 break;
1338
1339                 /*
1340                  *      For =* and !* operators, the value is irrelevant
1341                  *      so we return now.
1342                  */
1343         case T_OP_CMP_TRUE:
1344         case T_OP_CMP_FALSE:
1345                 vp->vp_strvalue[0] = '\0';
1346                 vp->length = 0;
1347                 return vp;
1348                 break;
1349
1350                 /*
1351                  *      Regular expression comparison of integer attributes
1352                  *      does a STRING comparison of the names of their
1353                  *      integer attributes.
1354                  */
1355         case T_OP_REG_EQ:       /* =~ */
1356         case T_OP_REG_NE:       /* !~ */
1357                 if (vp->type == PW_TYPE_INTEGER) {
1358                         return vp;
1359                 }
1360 #ifdef HAVE_REGEX_H
1361                 /*
1362                  *      Regular expression match with no regular
1363                  *      expression is wrong.
1364                  */
1365                 if (!value) {
1366                         pairfree(&vp);
1367                         return NULL;
1368                 }
1369
1370                 res = regcomp(&cre, value, REG_EXTENDED|REG_NOSUB);
1371                 if (res != 0) {
1372                         char    msg[128];
1373
1374                         regerror(res, &cre, msg, sizeof(msg));
1375                         librad_log("Illegal regular expression in attribute: %s: %s",
1376                                 vp->name, msg);
1377                         pairbasicfree(vp);
1378                         return NULL;
1379                 }
1380                 regfree(&cre);
1381 #else
1382                 librad_log("Regelar expressions not enabled in this build, error in attribute %s",
1383                                 vp->name);
1384                 pairbasicfree(vp);
1385                 return NULL;
1386 #endif
1387         }
1388
1389         /*
1390          *      FIXME: if (strcasecmp(attribute, vp->name) != 0)
1391          *      then the user MAY have typed in the attribute name
1392          *      as Vendor-%d-Attr-%d, and the value MAY be octets.
1393          *
1394          *      We probably want to fix pairparsevalue to accept
1395          *      octets as values for any attribute.
1396          */
1397         if (value && (pairparsevalue(vp, value) == NULL)) {
1398                 pairbasicfree(vp);
1399                 return NULL;
1400         }
1401
1402         return vp;
1403 }
1404
1405
1406 /*
1407  *      [a-zA-Z0-9_-:]+
1408  */
1409 static const int valid_attr_name[256] = {
1410         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1411         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1412         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
1413         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
1414         0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1415         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
1416         0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1417         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
1418         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1419         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1420         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1421         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1422         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1423         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1424         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1425         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1426 };
1427
1428 /*
1429  *      Read a valuepair from a buffer, and advance pointer.
1430  *      Sets *eol to T_EOL if end of line was encountered.
1431  */
1432 VALUE_PAIR *pairread(char **ptr, LRAD_TOKEN *eol)
1433 {
1434         char            buf[64];
1435         char            attr[64];
1436         char            value[512];
1437         char            *p, *q;
1438         LRAD_TOKEN      token, t, xlat;
1439         VALUE_PAIR      *vp;
1440         size_t          len;
1441
1442         *eol = T_OP_INVALID;
1443
1444         p = *ptr;
1445         while ((*p == ' ') || (*p == '\t')) p++;
1446
1447         if (!*p) {
1448                 *eol = T_OP_INVALID;
1449                 librad_log("No token read where we expected an attribute name");
1450                 return NULL;
1451         }
1452
1453         if (*p == '#') {
1454                 *eol = T_HASH;
1455                 librad_log("Read a comment instead of a token");
1456                 return NULL;
1457         }
1458
1459         q = attr;
1460         for (len = 0; len < sizeof(attr); len++) {
1461                 if (valid_attr_name[(int)*p]) {
1462                         *q++ = *p++;
1463                         continue;
1464                 }
1465                 break;
1466         }
1467
1468         if (len == sizeof(attr)) {
1469                 *eol = T_OP_INVALID;
1470                 librad_log("Attribute name is too long");
1471                 return NULL;
1472         }
1473
1474         /*
1475          *      We may have Foo-Bar:= stuff, so back up.
1476          */
1477         if (attr[len - 1] == ':') {
1478                 p--;
1479                 len--;
1480         }
1481
1482         attr[len] = '\0';
1483         *ptr = p;
1484
1485         /* Now we should have an operator here. */
1486         token = gettoken(ptr, buf, sizeof(buf));
1487         if (token < T_EQSTART || token > T_EQEND) {
1488                 librad_log("expecting operator");
1489                 return NULL;
1490         }
1491
1492         /* Read value.  Note that empty string values are allowed */
1493         xlat = gettoken(ptr, value, sizeof(value));
1494         if (xlat == T_EOL) {
1495                 librad_log("failed to get value");
1496                 return NULL;
1497         }
1498
1499         /*
1500          *      Peek at the next token. Must be T_EOL, T_COMMA, or T_HASH
1501          */
1502         p = *ptr;
1503         t = gettoken(&p, buf, sizeof(buf));
1504         if (t != T_EOL && t != T_COMMA && t != T_HASH) {
1505                 librad_log("Expected end of line or comma");
1506                 return NULL;
1507         }
1508
1509         *eol = t;
1510         if (t == T_COMMA) {
1511                 *ptr = p;
1512         }
1513
1514         vp = NULL;
1515         switch (xlat) {
1516                 /*
1517                  *      Make the full pair now.
1518                  */
1519         default:
1520                 vp = pairmake(attr, value, token);
1521                 break;
1522
1523                 /*
1524                  *      Perhaps do xlat's
1525                  */
1526         case T_DOUBLE_QUOTED_STRING:
1527                 p = strchr(value, '%');
1528                 if (p && (p[1] == '{')) {
1529                         if (strlen(value) >= sizeof(vp->vp_strvalue)) {
1530                                 librad_log("Value too long");
1531                                 return NULL;
1532                         }
1533                         vp = pairmake(attr, NULL, token);
1534                         if (!vp) {
1535                                 *eol = T_OP_INVALID;
1536                                 return NULL;
1537                         }
1538
1539                         strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
1540                         vp->flags.do_xlat = 1;
1541                         vp->length = 0;
1542                 } else {
1543                         vp = pairmake(attr, value, token);
1544                 }
1545                 break;
1546
1547
1548                 /*
1549                  *      Mark the pair to be allocated later.
1550                  */
1551         case T_BACK_QUOTED_STRING:
1552                 if (strlen(value) >= sizeof(vp->vp_strvalue)) {
1553                         librad_log("Value too long");
1554                         return NULL;
1555                 }
1556
1557                 vp = pairmake(attr, NULL, token);
1558                 if (!vp) {
1559                         *eol = T_OP_INVALID;
1560                         return NULL;
1561                 }
1562
1563                 vp->flags.do_xlat = 1;
1564                 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
1565                 vp->length = 0;
1566                 break;
1567         }
1568
1569         /*
1570          *      If we didn't make a pair, return an error.
1571          */
1572         if (!vp) {
1573                 *eol = T_OP_INVALID;
1574                 return NULL;
1575         }
1576
1577         return vp;
1578 }
1579
1580 /*
1581  *      Read one line of attribute/value pairs. This might contain
1582  *      multiple pairs seperated by comma's.
1583  */
1584 LRAD_TOKEN userparse(char *buffer, VALUE_PAIR **first_pair)
1585 {
1586         VALUE_PAIR      *vp;
1587         char            *p;
1588         LRAD_TOKEN      last_token = T_OP_INVALID;
1589         LRAD_TOKEN      previous_token;
1590
1591         /*
1592          *      We allow an empty line.
1593          */
1594         if (buffer[0] == 0)
1595                 return T_EOL;
1596
1597         p = buffer;
1598         do {
1599                 previous_token = last_token;
1600                 if ((vp = pairread(&p, &last_token)) == NULL) {
1601                         return last_token;
1602                 }
1603                 pairadd(first_pair, vp);
1604         } while (*p && (last_token == T_COMMA));
1605
1606         /*
1607          *      Don't tell the caller that there was a comment.
1608          */
1609         if (last_token == T_HASH) {
1610                 return previous_token;
1611         }
1612
1613         /*
1614          *      And return the last token which we read.
1615          */
1616         return last_token;
1617 }
1618
1619 /*
1620  *      Read valuepairs from the fp up to End-Of-File.
1621  *
1622  *      Hmm... this function is only used by radclient..
1623  */
1624 VALUE_PAIR *readvp2(FILE *fp, int *pfiledone, const char *errprefix)
1625 {
1626         char buf[8192];
1627         LRAD_TOKEN last_token = T_EOL;
1628         VALUE_PAIR *vp;
1629         VALUE_PAIR *list;
1630         int error = 0;
1631
1632         list = NULL;
1633
1634         while (!error && fgets(buf, sizeof(buf), fp) != NULL) {
1635                 /*
1636                  *      If we get a '\n' by itself, we assume that's
1637                  *      the end of that VP
1638                  */
1639                 if ((buf[0] == '\n') && (list)) {
1640                         return list;
1641                 }
1642                 if ((buf[0] == '\n') && (!list)) {
1643                         continue;
1644                 }
1645
1646                 /*
1647                  *      Comments get ignored
1648                  */
1649                 if (buf[0] == '#') continue;
1650
1651                 /*
1652                  *      Read all of the attributes on the current line.
1653                  */
1654                 vp = NULL;
1655                 last_token = userparse(buf, &vp);
1656                 if (!vp) {
1657                         if (last_token != T_EOL) {
1658                                 librad_perror("%s", errprefix);
1659                                 error = 1;
1660                                 break;
1661                         }
1662                         break;
1663                 }
1664
1665                 pairadd(&list, vp);
1666                 buf[0] = '\0';
1667         }
1668
1669         if (error) pairfree(&list);
1670
1671         *pfiledone = 1;
1672
1673         return error ? NULL: list;
1674 }
1675
1676
1677
1678 /*
1679  *      Compare two pairs, using the operator from "one".
1680  *
1681  *      i.e. given two attributes, it does:
1682  *
1683  *      (two->data) (one->operator) (one->data)
1684  *
1685  *      e.g. "foo" != "bar"
1686  *
1687  *      Returns true (comparison is true), or false (comparison is not true);
1688  */
1689 int paircmp(VALUE_PAIR *one, VALUE_PAIR *two)
1690 {
1691         int compare;
1692
1693         switch (one->operator) {
1694         case T_OP_CMP_TRUE:
1695                 return (two != NULL);
1696
1697         case T_OP_CMP_FALSE:
1698                 return (two == NULL);
1699
1700                 /*
1701                  *      One is a regex, compile it, print two to a string,
1702                  *      and then do string comparisons.
1703                  */
1704         case T_OP_REG_EQ:
1705         case T_OP_REG_NE:
1706 #ifndef HAVE_REGEX_H
1707                 return -1;
1708 #else
1709                 {
1710                         regex_t reg;
1711                         char buffer[MAX_STRING_LEN * 4 + 1];
1712
1713                         compare = regcomp(&reg, one->vp_strvalue,
1714                                           REG_EXTENDED);
1715                         if (compare != 0) {
1716                                 regerror(compare, &reg, buffer, sizeof(buffer));
1717                                 librad_log("Illegal regular expression in attribute: %s: %s",
1718                                            one->name, buffer);
1719                                 return -1;
1720                         }
1721
1722                         vp_prints_value(buffer, sizeof(buffer), two, 0);
1723
1724                         /*
1725                          *      Don't care about substring matches,
1726                          *      oh well...
1727                          */
1728                         compare = regexec(&reg, buffer, 0, NULL, 0);
1729
1730                         regfree(&reg);
1731                         if (one->operator == T_OP_REG_EQ) return (compare == 0);
1732                         return (compare != 0);
1733                 }
1734 #endif
1735
1736         default:                /* we're OK */
1737                 break;
1738         }
1739
1740         /*
1741          *      After doing the previous check for special comparisons,
1742          *      do the per-type comparison here.
1743          */
1744         switch (one->type) {
1745         case PW_TYPE_ABINARY:
1746         case PW_TYPE_OCTETS:
1747         {
1748                 size_t length;
1749                 const uint8_t *p, *q;
1750
1751                 if (one->length < two->length) {
1752                         length = one->length;
1753                 } else {
1754                         length = two->length;
1755                 }
1756
1757                 p = two->vp_octets;
1758                 q = one->vp_octets;
1759                 while (length) {
1760                         compare = ((int) *p) - ((int) *q);
1761                         if (compare != 0) goto type_switch;
1762                 }
1763
1764                 /*
1765                  *      Contents are the same.  The return code
1766                  *      is therefore the difference in lengths.
1767                  *
1768                  *      i.e. "0x00" is smaller than "0x0000"
1769                  */
1770                 compare = two->length - one->length;
1771         }
1772                 break;
1773
1774         case PW_TYPE_STRING:
1775                 if (one->flags.caseless) {
1776                         compare = strcasecmp(two->vp_strvalue,
1777                                              one->vp_strvalue);
1778                 } else {
1779                         compare = strcmp(two->vp_strvalue,
1780                                          one->vp_strvalue);
1781                 }
1782                 break;
1783
1784         case PW_TYPE_BYTE:
1785         case PW_TYPE_SHORT:
1786         case PW_TYPE_INTEGER:
1787         case PW_TYPE_DATE:
1788                 compare = two->vp_integer - one->vp_integer;
1789                 break;
1790
1791         case PW_TYPE_IPADDR:
1792                 compare = ntohl(two->vp_ipaddr) - ntohl(one->vp_ipaddr);
1793                 break;
1794
1795         case PW_TYPE_IPV6ADDR:
1796                 compare = memcmp(&two->vp_ipv6addr, &one->vp_ipv6addr,
1797                                  sizeof(two->vp_ipv6addr));
1798                 break;
1799
1800         case PW_TYPE_IPV6PREFIX:
1801                 compare = memcmp(&two->vp_ipv6prefix, &one->vp_ipv6prefix,
1802                                  sizeof(two->vp_ipv6prefix));
1803                 break;
1804
1805         case PW_TYPE_IFID:
1806                 compare = memcmp(&two->vp_ifid, &one->vp_ifid,
1807                                  sizeof(two->vp_ifid));
1808                 break;
1809
1810         default:
1811                 return 0;       /* unknown type */
1812         }
1813
1814         /*
1815          *      Now do the operator comparison.
1816          */
1817  type_switch:
1818         switch (one->operator) {
1819         case T_OP_CMP_EQ:
1820                 return (compare == 0);
1821
1822         case T_OP_NE:
1823                 return (compare != 0);
1824
1825         case T_OP_LT:
1826                 return (compare < 0);
1827
1828         case T_OP_GT:
1829                 return (compare > 0);
1830
1831         case T_OP_LE:
1832                 return (compare <= 0);
1833
1834         case T_OP_GE:
1835                 return (compare >= 0);
1836
1837         default:
1838                 return 0;
1839         }
1840
1841         return 0;
1842 }