Radcli library 2.0.0
A simple radius library -- legacy API reference
Loading...
Searching...
No Matches
avpair.c
1/*
2 * Copyright (C) 2015 Nikos Mavrogiannopoulos
3 * Copyright (C) 1995 Lars Fenneberg
4 *
5 * Copyright 1992 Livingston Enterprises, Inc.
6 *
7 * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan
8 * and Merit Network, Inc. All Rights Reserved
9 *
10 * See the file COPYRIGHT for the respective terms and conditions.
11 * If the file is missing contact me at lf@elemental.net
12 * and I'll send you a copy.
13 *
14 */
15#include <config.h>
16#include <includes.h>
17#include <radcli/radcli.h>
18#include "dict2.h"
19#include "util.h"
20
21#define PARSE_MODE_NAME 0
22#define PARSE_MODE_EQUAL 1
23#define PARSE_MODE_VALUE 2
24#define PARSE_MODE_INVALID 3
25
32
47VALUE_PAIR *rc_avpair_add (rc_handle const *rh, VALUE_PAIR **list, uint32_t attrid, void const *pval, int len, uint32_t vendorspec)
48{
49 VALUE_PAIR *vp;
50
51 vp = rc_avpair_new (rh, attrid, pval, len, vendorspec);
52
53 if (vp != NULL)
54 {
55 rc_avpair_insert (list, NULL, vp);
56 }
57
58 return vp;
59
60}
61
70void rc_avpair_remove (VALUE_PAIR **list, uint32_t attrid, uint32_t vendorspec)
71{
72 VALUE_PAIR *vp, *prev, *tmp;
73 uint64_t vattrid;
74
75 if(vendorspec != VENDOR_NONE)
76 vattrid = RADCLI_VENDOR_ATTR_SET(attrid, vendorspec);
77 else
78 vattrid = attrid;
79
80 prev = NULL;
81 vp = *list;
82 while(vp != NULL) {
83 if (vp->attribute == vattrid) {
84 /* found */
85 if (prev == NULL) { /* first one */
86 tmp = vp;
87 vp = tmp->next;
88 free(tmp);
89 *list = vp;
90 } else { /* somewhere in the middle */
91 prev->next = vp->next;
92 free(vp);
93 }
94 break;
95 }
96
97 prev = vp;
98 vp = vp->next;
99 };
100
101 return;
102}
103
113VALUE_PAIR *rc_avpair_next (VALUE_PAIR *t)
114{
115 return t->next;
116}
117
136int rc_avpair_assign (VALUE_PAIR *vp, void const *pval, int len)
137{
138
139 switch (vp->type)
140 {
141 case PW_TYPE_STRING:
142 if (len == -1)
143 len = (uint32_t)strlen((char const *)pval);
144 /* Vendor-specific attributes use additionally 6 bytes of envelope
145 * (4 vendor-id + 1 sub-type + 1 sub-length) thus reduce the AUTH_STRING_LEN
146 * (253-byte value) to 247. */
147 if (len > (int)(VENDOR(vp->attribute) ? (AUTH_STRING_LEN - VSA_HDR_LEN) : (AUTH_STRING_LEN))) {
148 rc_log(LOG_ERR, "rc_avpair_assign: bad attribute length");
149 return -1;
150 }
151 memcpy(vp->strvalue, (char const *)pval, len);
152 vp->strvalue[len] = '\0';
153 vp->lvalue = len;
154 break;
155
156 case PW_TYPE_DATE:
157 case PW_TYPE_INTEGER:
158 case PW_TYPE_IPADDR:
159 vp->lvalue = * (uint32_t *) pval;
160 break;
161 case PW_TYPE_IPV6ADDR:
162 if (len != 16) {
163 rc_log(LOG_ERR, "rc_avpair_assign: bad IPv6 length");
164 return -1;
165 }
166 memcpy(vp->strvalue, (char const *)pval, len);
167 vp->lvalue = len;
168 break;
169
171 if (len < 2 || len > 18) {
172 rc_log(LOG_ERR, "rc_avpair_assign: bad IPv6 prefix length");
173 return -1;
174 }
175 memcpy(vp->strvalue, (char const *)pval, len);
176 vp->lvalue = len;
177 break;
178
179 default:
180 rc_log(LOG_ERR, "rc_avpair_assign: no attribute %d in dictionary", vp->type);
181 return -1;
182 }
183 return 0;
184}
185
197VALUE_PAIR *rc_avpair_new (rc_handle const *rh, uint32_t attrid, void const *pval, int len, uint32_t vendorspec)
198{
199 VALUE_PAIR *vp = NULL;
200 struct radcli_dict_attr *pda;
201 uint64_t vattrid;
202
203 if(vendorspec != VENDOR_NONE) {
204 vattrid = RADCLI_VENDOR_ATTR_SET(attrid, vendorspec);
205 } else {
206 vattrid = attrid;
207 }
208
209 if ((pda = radcli_dict_attr_by_id (rh, vattrid)) == NULL)
210 {
211 rc_log(LOG_ERR,"rc_avpair_new: no attribute %d/%u in dictionary", vendorspec, attrid);
212 return NULL;
213 }
214 if (vendorspec != 0 && radcli_dict_vendor_by_pec(rh, vendorspec) == NULL)
215 {
216 rc_log(LOG_ERR,"rc_avpair_new: no Vendor-Id %d in dictionary", vendorspec);
217 return NULL;
218 }
219 if ((vp = malloc (sizeof (VALUE_PAIR))) != NULL)
220 {
221 strlcpy (vp->name, pda->name, sizeof (vp->name));
222 vp->attribute = vattrid;
223 vp->next = NULL;
224 vp->type = radcli_dict_type_to_legacy(pda->type);
225 if (rc_avpair_assign (vp, pval, len) == 0)
226 {
227 return vp;
228 }
229 free (vp);
230 vp = NULL;
231 }
232 else
233 {
234 rc_log(LOG_CRIT,"rc_avpair_new: out of memory");
235 }
236
237 return vp;
238}
239
240/*- Decode a run of RADIUS attribute TLVs from pb, prepending onto pair.
241 *
242 * @param rh a handle to parsed configuration.
243 * @param pair existing VALUE_PAIR list to prepend the decoded attributes
244 * onto; freed on hard error.
245 * @param pb the buffer to decode attributes from.
246 * @param vendorspec 0 when decoding top-level attributes, or the
247 * enclosing vendor's PEN when recursing into a VSA's sub-attributes.
248 * @param out set to the decoded list on success (may be NULL if every
249 * attribute was skipped).
250 * @return 0 on success, -1 on a hard error (*out undefined, pair freed).
251 -*/
252static int rc_avpair_gen2(rc_handle const *rh, VALUE_PAIR *pair,
253 pkt_buf *pb, uint32_t vendorspec,
254 VALUE_PAIR **out)
255{
256 VALUE_PAIR *head = pair;
257 VALUE_PAIR **tail = &head;
258 const uint8_t *attr_data, *ptr;
259 int attrlen;
260 uint64_t attribute;
261 uint32_t lvalue;
262 struct radcli_dict_attr *attr;
263 VALUE_PAIR *rpair;
264 char buffer[(AUTH_STRING_LEN * 2) + 1];
265
266 /* Advance tail to end of the initial list so we append in wire order */
267 while (*tail != NULL)
268 tail = &(*tail)->next;
269
270 while (pb_len(pb) > 0) {
271 if (pb_len(pb) < 2) {
272 rc_log(LOG_ERR, "rc_avpair_gen: received attribute with "
273 "invalid length");
274 goto error;
275 }
276 attrlen = pb->data[1];
277 if (attrlen < 2 || (size_t)attrlen > pb_len(pb)) {
278 rc_log(LOG_ERR, "rc_avpair_gen: received attribute with "
279 "invalid length");
280 goto error;
281 }
282
283 attr_data = pb->data;
284 assert(pb_pull(pb, attrlen) == 0);
285
286 attribute = RADCLI_VENDOR_ATTR_SET(attr_data[0], vendorspec);
287 ptr = attr_data + 2;
288 attrlen -= 2;
289
290 /* VSA */
291 if (attribute == PW_VENDOR_SPECIFIC) {
292 if (attrlen < 4) {
293 rc_log(LOG_ERR, "rc_avpair_gen: received VSA "
294 "attribute with invalid length");
295 continue;
296 }
297 memcpy(&lvalue, ptr, 4);
298 lvalue = ntohl(lvalue);
299 if (radcli_dict_vendor_by_pec(rh, lvalue) == NULL) {
300 rc_log(LOG_WARNING, "rc_avpair_gen: received VSA "
301 "attribute with unknown Vendor-Id %d", lvalue);
302 continue;
303 }
304 /* Process VSA sub-attributes; append results to tail */
305 {
306 pkt_buf vsa_pb;
307 VALUE_PAIR *vsa_list = NULL;
308 pb_init_read(&vsa_pb,
309 (void *)(uintptr_t)(ptr + 4),
310 attrlen - 4, attrlen - 4);
311 if (rc_avpair_gen2(rh, NULL, &vsa_pb, lvalue,
312 &vsa_list) < 0)
313 goto error;
314 /* vsa_list may be NULL if all sub-attrs skipped */
315 if (vsa_list != NULL) {
316 *tail = vsa_list;
317 while (*tail != NULL)
318 tail = &(*tail)->next;
319 }
320 }
321 continue;
322 }
323
324 /* Normal attribute */
325 attr = radcli_dict_attr_by_id(rh, attribute);
326 if (attr == NULL) {
327 rc_bin2hex(buffer, sizeof(buffer), ptr, (size_t)attrlen);
328 if (vendorspec == 0) {
329 rc_log(LOG_WARNING, "rc_avpair_gen: received "
330 "unknown attribute %d of length %d: 0x%s",
331 (unsigned)attribute, attrlen + 2, buffer);
332 } else {
333 rc_log(LOG_WARNING, "rc_avpair_gen: received "
334 "unknown VSA attribute %u, vendor %u of "
335 "length %d: 0x%s", (unsigned)ATTRID(attribute),
336 (unsigned)VENDOR(attribute), attrlen + 2, buffer);
337 }
338 continue;
339 }
340
341 rpair = calloc(1, sizeof(*rpair));
342 if (rpair == NULL) {
343 rc_log(LOG_CRIT, "rc_avpair_gen: out of memory");
344 goto error;
345 }
346 rpair->next = NULL;
347 strlcpy(rpair->name, attr->name, sizeof(rpair->name));
348 rpair->attribute = attr->value;
349 rpair->type = radcli_dict_type_to_legacy(attr->type);
350
351 switch (rpair->type) {
352 case PW_TYPE_STRING:
353 if (attrlen > AUTH_STRING_LEN) {
354 rc_log(LOG_ERR, "rc_avpair_gen: string attribute too long: %d", attrlen);
355 free(rpair);
356 goto error;
357 }
358 memcpy(rpair->strvalue, (char *)ptr, (size_t)attrlen);
359 rpair->strvalue[attrlen] = '\0';
360 rpair->lvalue = attrlen;
361 break;
362 case PW_TYPE_INTEGER:
363 case PW_TYPE_IPADDR:
364 if (attrlen != 4) {
365 rc_log(LOG_ERR, "rc_avpair_gen: received "
366 "INTEGER/IPADDR attribute with invalid length");
367 free(rpair);
368 continue;
369 }
370 memcpy((char *)&lvalue, (char *)ptr, 4);
371 rpair->lvalue = ntohl(lvalue);
372 break;
373 case PW_TYPE_IPV6ADDR:
374 if (attrlen != 16) {
375 rc_log(LOG_ERR, "rc_avpair_gen: received IPV6ADDR"
376 " attribute with invalid length");
377 free(rpair);
378 continue;
379 }
380 memcpy(rpair->strvalue, (char *)ptr, 16);
381 rpair->lvalue = attrlen;
382 break;
384 if (attrlen > 18 || attrlen < 2) {
385 rc_log(LOG_ERR, "rc_avpair_gen: received IPV6PREFIX"
386 " attribute with invalid length: %d", attrlen);
387 free(rpair);
388 continue;
389 }
390 memcpy(rpair->strvalue, (char *)ptr, attrlen);
391 rpair->lvalue = attrlen;
392 break;
393 case PW_TYPE_DATE:
394 if (attrlen != 4) {
395 rc_log(LOG_ERR, "rc_avpair_gen: received DATE "
396 "attribute with invalid length");
397 free(rpair);
398 continue;
399 }
400 memcpy((char *)&lvalue, (char *)ptr, 4);
401 rpair->lvalue = ntohl(lvalue);
402 break;
403 default:
404 rc_log(LOG_WARNING, "rc_avpair_gen: %s has unknown type",
405 attr->name);
406 free(rpair);
407 continue;
408 }
409
410 *tail = rpair;
411 tail = &rpair->next;
412 }
413
414 *out = head;
415 return 0;
416
417error:
418 rc_avpair_free(head);
419 return -1;
420}
421
444VALUE_PAIR *rc_avpair_gen(rc_handle const *rh, VALUE_PAIR *pair,
445 unsigned char const *ptr, int length,
446 uint32_t vendorspec)
447{
448 pkt_buf pb;
449 VALUE_PAIR *out = NULL;
450 if (length <= 0)
451 return pair;
452 pb_init_read(&pb, (void *)ptr, (size_t)length, (size_t)length);
453 if (rc_avpair_gen2(rh, pair, &pb, vendorspec, &out) < 0)
454 return NULL;
455 return out;
456}
457
465VALUE_PAIR *rc_avpair_get (VALUE_PAIR *vp, uint32_t attrid, uint32_t vendorspec)
466{
467 uint64_t attr = RADCLI_VENDOR_ATTR_SET(attrid, vendorspec);
468
469 for (; vp != NULL && !(attr == vp->attribute); vp = vp->next)
470 {
471 continue;
472 }
473 return vp;
474}
475
482VALUE_PAIR *rc_avpair_copy(VALUE_PAIR *p)
483{
484 VALUE_PAIR *vp, *fp = NULL, *lp = NULL;
485
486 while (p) {
487 vp = malloc(sizeof(VALUE_PAIR));
488 if (!vp) {
489 while(fp) { /* free allocated memory */
490 vp = fp;
491 fp = fp->next;
492 free(vp);
493 }
494 return NULL;
495 }
496 *vp = *p;
497 if (!fp)
498 fp = vp;
499 if (lp)
500 lp->next = vp;
501 lp = vp;
502 p = p->next;
503 }
504
505 return fp;
506}
507
517void rc_avpair_insert(VALUE_PAIR **a, VALUE_PAIR *p, VALUE_PAIR *b)
518{
519 VALUE_PAIR *this_node = NULL;
520 VALUE_PAIR *vp;
521
522 if (b->next != NULL)
523 {
524 rc_log(LOG_CRIT, "rc_avpair_insert: value pair (0x%p) next ptr. (0x%p) not NULL", b, b->next);
525 abort ();
526 }
527
528 if (*a == NULL)
529 {
530 *a = b;
531 return;
532 }
533
534 vp = *a;
535
536 if ( p == NULL) /* run to end of "a" list */
537 {
538 while (vp != NULL)
539 {
540 this_node = vp;
541 vp = vp->next;
542 }
543 }
544 else /* look for the "p" entry in the "a" list */
545 {
546 this_node = *a;
547 while (this_node != NULL)
548 {
549 if (this_node == p)
550 {
551 break;
552 }
553 this_node = this_node->next;
554 }
555 }
556
557 if (this_node) {
558 b->next = this_node->next;
559 this_node->next = b;
560 }
561
562 return;
563}
564
569void rc_avpair_free (VALUE_PAIR *pair)
570{
571 VALUE_PAIR *next;
572
573 while (pair != NULL)
574 {
575 next = pair->next;
576 free (pair);
577 pair = next;
578 }
579}
580
581/*- Copy a data field from the buffer, advancing *uptr past it. No more
582 * than len - 1 bytes are copied, and string is always NUL-terminated.
583 *
584 * @param string the destination buffer to copy into.
585 * @param uptr the current position of the buffer; advanced past the field.
586 * @param stopat characters at which parsing should stop.
587 * @param len the maximum length of string.
588 -*/
589static void rc_fieldcpy(char *string, char const **uptr, char const *stopat, size_t len)
590{
591 char const *ptr, *estring;
592
593 ptr = *uptr;
594 estring = string + len - 1;
595 if (*ptr == '"')
596 {
597 ptr++;
598 while (*ptr != '"' && *ptr != '\0' && *ptr != '\n')
599 {
600 if (string < estring)
601 *string++ = *ptr;
602 ptr++;
603 }
604 if (*ptr == '"')
605 {
606 ptr++;
607 }
608 *string = '\0';
609 *uptr = ptr;
610 return;
611 }
612
613 while (*ptr != '\0' && strchr(stopat, *ptr) == NULL)
614 {
615 if (string < estring)
616 *string++ = *ptr;
617 ptr++;
618 }
619 *string = '\0';
620 *uptr = ptr;
621 return;
622}
623
631int rc_avpair_parse (rc_handle const *rh, char const *buffer, VALUE_PAIR **first_pair)
632{
633 int mode;
634 char attrstr[AUTH_ID_LEN];
635 char valstr[AUTH_STRING_LEN + 1], *p;
636 struct radcli_dict_attr *attr = NULL;
637 struct radcli_dict_value *dval;
638 VALUE_PAIR *pair;
639 VALUE_PAIR *link;
640 struct tm *tm, _tm;
641 time_t timeval;
642
643 mode = PARSE_MODE_NAME;
644 while (*buffer != '\n' && *buffer != '\0')
645 {
646 if (*buffer == ' ' || *buffer == '\t')
647 {
648 buffer++;
649 continue;
650 }
651
652 switch (mode)
653 {
654 case PARSE_MODE_NAME: /* Attribute Name */
655 rc_fieldcpy (attrstr, &buffer, " \t\n=,", sizeof(attrstr));
656 if ((attr =
657 radcli_dict_attr_by_name (rh, attrstr)) == NULL)
658 {
659 rc_log(LOG_ERR, "rc_avpair_parse: unknown attribute");
660 if (*first_pair) {
661 rc_avpair_free(*first_pair);
662 *first_pair = NULL;
663 }
664 return -1;
665 }
666 mode = PARSE_MODE_EQUAL;
667 break;
668
669 case PARSE_MODE_EQUAL: /* Equal sign */
670 if (*buffer == '=')
671 {
672 mode = PARSE_MODE_VALUE;
673 buffer++;
674 }
675 else
676 {
677 rc_log(LOG_ERR, "rc_avpair_parse: missing or misplaced equal sign");
678 if (*first_pair) {
679 rc_avpair_free(*first_pair);
680 *first_pair = NULL;
681 }
682 return -1;
683 }
684 break;
685
686 case PARSE_MODE_VALUE: /* Value */
687 rc_fieldcpy (valstr, &buffer, " \t\n,", sizeof(valstr));
688
689 if ((pair = malloc (sizeof (VALUE_PAIR))) == NULL)
690 {
691 rc_log(LOG_CRIT, "rc_avpair_parse: out of memory");
692 if (*first_pair) {
693 rc_avpair_free(*first_pair);
694 *first_pair = NULL;
695 }
696 return -1;
697 }
698 strlcpy (pair->name, attr->name, sizeof(pair->name));
699 pair->attribute = attr->value;
700 pair->type = radcli_dict_type_to_legacy(attr->type);
701
702 switch (pair->type)
703 {
704
705 case PW_TYPE_STRING:
706 if (rc_avpair_assign(pair, valstr, strlen(valstr)) < 0) {
707 rc_log(LOG_ERR, "rc_avpair_parse: string value too long");
708 free(pair);
709 return -1;
710 }
711 break;
712
713 case PW_TYPE_INTEGER:
714 if (isdigit (*valstr))
715 {
716 pair->lvalue = atoi (valstr);
717 }
718 else
719 {
720 if ((dval = radcli_dict_value_by_name (rh, valstr))
721 == NULL)
722 {
723 rc_log(LOG_ERR, "rc_avpair_parse: unknown attribute value: %s", valstr);
724 if (*first_pair) {
725 rc_avpair_free(*first_pair);
726 *first_pair = NULL;
727 }
728 free (pair);
729 return -1;
730 }
731 else
732 {
733 pair->lvalue = dval->value;
734 }
735 }
736 break;
737
738 case PW_TYPE_IPADDR:
739 if (inet_pton(AF_INET, valstr, &pair->lvalue) == 0) {
740 rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv4 address %s", valstr);
741 free(pair);
742 return -1;
743 }
744
745 pair->lvalue = ntohl(pair->lvalue);
746 break;
747
748 case PW_TYPE_IPV6ADDR:
749 if (inet_pton(AF_INET6, valstr, pair->strvalue) == 0) {
750 rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv6 address %s", valstr);
751 free(pair);
752 return -1;
753 }
754 pair->lvalue = 16;
755 break;
756
758 p = strchr(valstr, '/');
759 if (p == NULL) {
760 rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv6 prefix %s", valstr);
761 free(pair);
762 return -1;
763 }
764 *p = 0;
765 p++;
766 pair->strvalue[0] = 0;
767 pair->strvalue[1] = atoi(p);
768
769 if (inet_pton(AF_INET6, valstr, pair->strvalue+2) == 0) {
770 rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv6 prefix %s", valstr);
771 free(pair);
772 return -1;
773 }
774 pair->lvalue = 2+16;
775 break;
776
777 case PW_TYPE_DATE:
778 timeval = time (0);
779 tm = localtime_r (&timeval, &_tm);
780 tm->tm_hour = 0;
781 tm->tm_min = 0;
782 tm->tm_sec = 0;
783 if (rc_str2tm (valstr, tm) < 0) {
784 rc_log(LOG_ERR, "rc_avpair_parse: invalid date %s", valstr);
785 free(pair);
786 return -1;
787 }
788 pair->lvalue = (uint32_t) mktime (tm);
789 break;
790
791 default:
792 rc_log(LOG_ERR, "rc_avpair_parse: unknown attribute type %d", pair->type);
793 if (*first_pair) {
794 rc_avpair_free(*first_pair);
795 *first_pair = NULL;
796 }
797 free (pair);
798 return -1;
799 }
800
801 pair->next = NULL;
802
803 if (*first_pair == NULL)
804 {
805 *first_pair = pair;
806 }
807 else
808 {
809 link = *first_pair;
810 while (link->next != NULL)
811 {
812 link = link->next;
813 }
814 link->next = pair;
815 }
816
817 mode = PARSE_MODE_NAME;
818 break;
819
820 default:
821 mode = PARSE_MODE_NAME;
822 break;
823 }
824 }
825 return 0;
826}
827
838int rc_avpair_tostr (rc_handle const *rh, VALUE_PAIR *pair, char *name, int ln, char *value, int lv)
839{
840 struct radcli_dict_value *dval;
841 struct in_addr inad;
842 unsigned char *ptr;
843 unsigned int pos;
844 unsigned int slen;
845
846 *name = *value = '\0';
847
848 if (!pair || pair->name[0] == '\0') {
849 rc_log(LOG_ERR, "rc_avpair_tostr: pair is NULL or empty");
850 return -1;
851 }
852
853 strlcpy(name, pair->name, (size_t) ln);
854
855 switch (pair->type)
856 {
857 case PW_TYPE_STRING:
858 lv--;
859 pos = 0;
860 ptr = (unsigned char *) pair->strvalue;
861 slen = pair->lvalue;
862 while (slen-- > 0)
863 {
864 if (!(isprint (*ptr)))
865 {
866 if (lv >= 4) {
867 snprintf (&value[pos], lv, "\\%03o", *ptr);
868 pos += 4;
869 lv -= 4;
870 } else {
871 break;
872 }
873 }
874 else
875 {
876 if (lv > 0) {
877 value[pos++] = *ptr;
878 lv--;
879 } else {
880 break;
881 }
882 }
883 ptr++;
884 }
885 value[pos] = 0;
886 break;
887
888 case PW_TYPE_INTEGER:
889 dval = radcli_dict_value_by_attr (rh, pair->name, pair->lvalue);
890 if (dval != NULL)
891 {
892 strlcpy(value, dval->name, (size_t) lv);
893 }
894 else
895 {
896 snprintf(value, lv, "%ld", (long int)pair->lvalue);
897 }
898 break;
899
900 case PW_TYPE_IPADDR:
901 inad.s_addr = htonl(pair->lvalue);
902 strlcpy (value, inet_ntoa (inad), (size_t) lv);
903 break;
904
905 case PW_TYPE_IPV6ADDR:
906 if (inet_ntop(AF_INET6, pair->strvalue, value, lv) == NULL)
907 return -1;
908 break;
909
910 case PW_TYPE_IPV6PREFIX: {
911 uint8_t ip[16];
912 uint8_t txt[48];
913 if (pair->lvalue < 2)
914 return -1;
915
916 memset(ip, 0, sizeof(ip));
917 memcpy(ip, pair->strvalue+2, pair->lvalue-2);
918
919 if (inet_ntop(AF_INET6, ip, (void*)txt, sizeof(txt)) == NULL)
920 return -1;
921 snprintf(value, lv, "%s/%u", txt, (unsigned)pair->strvalue[1]);
922
923 break;
924 }
925 case PW_TYPE_DATE: {
926 struct tm _tm;
927 struct tm *ptm = gmtime_r((time_t *) & pair->lvalue, &_tm);
928 if (ptm == NULL)
929 return -1;
930
931 strftime (value, lv, "%m/%d/%y %H:%M:%S", ptm);
932 break;
933 }
934
935 default:
936 rc_log(LOG_ERR, "rc_avpair_tostr: unknown attribute type %d", pair->type);
937 return -1;
938 break;
939 }
940
941 return 0;
942}
943
954char *rc_avpair_log(rc_handle const *rh, VALUE_PAIR *pair, char *buf, size_t buf_len)
955{
956 size_t len;
957 int n;
958 VALUE_PAIR *vp;
959 char name[RC_NAME_LENGTH + 1], value[256];
960
961 len = 0;
962 for (vp = pair; vp != NULL; vp = vp->next) {
963 if (rc_avpair_tostr(rh, vp, name, sizeof(name), value,
964 sizeof(value)) == -1)
965 return NULL;
966 if (len >= buf_len)
967 return buf;
968 n = snprintf(buf + len, buf_len - len, "%-32s = '%s'\n", name, value);
969 if (n < 0 || (size_t)n >= buf_len - len)
970 return buf;
971 len += (size_t)n;
972 }
973 return buf;
974}
975
986int rc_avpair_get_uint32 (VALUE_PAIR *vp, uint32_t *res)
987{
988 if (vp->type == PW_TYPE_DATE || vp->type == PW_TYPE_IPADDR ||
989 vp->type == PW_TYPE_INTEGER) {
990 if (res)
991 *res = vp->lvalue;
992 return 0;
993 } else {
994 return -1;
995 }
996}
997
1007int rc_avpair_get_in6 (VALUE_PAIR *vp, struct in6_addr *res, unsigned *prefix)
1008{
1009 if (vp->type == PW_TYPE_IPV6ADDR) {
1010 memcpy(res, vp->strvalue, 16);
1011 return 0;
1012 } else if (vp->type == PW_TYPE_IPV6PREFIX) {
1013 if (vp->lvalue < 2 || vp->lvalue > 18)
1014 return -1;
1015
1016 if (res) {
1017 memset(res, 0, 16);
1018 memcpy(res, vp->strvalue+2, vp->lvalue-2);
1019 }
1020
1021 if (prefix)
1022 *prefix = (unsigned char)vp->strvalue[1];
1023 return 0;
1024 }
1025
1026 return -1;
1027}
1028
1039int rc_avpair_get_raw (VALUE_PAIR *vp, char **res, unsigned *res_size)
1040{
1041 if (vp->type == PW_TYPE_STRING || vp->type == PW_TYPE_IPV6ADDR ||
1042 vp->type == PW_TYPE_IPV6PREFIX) {
1043 if (res)
1044 *res = vp->strvalue;
1045 if (res_size)
1046 *res_size = vp->lvalue;
1047 return 0;
1048 } else {
1049 return -1;
1050 }
1051}
1052
1059void rc_avpair_get_attr (VALUE_PAIR *vp, unsigned *type, unsigned *id)
1060{
1061 if (type)
1062 *type = vp->type;
1063 if (id)
1064 *id = vp->attribute;
1065}
1066
1068/*
1069 * Local Variables:
1070 * c-basic-offset:8
1071 * c-style: whitesmith
1072 * End:
1073 */
void rc_avpair_remove(VALUE_PAIR **list, uint32_t attrid, uint32_t vendorspec)
Removes an attribute-value pair from the given list.
Definition avpair.c:70
int rc_avpair_get_raw(VALUE_PAIR *vp, char **res, unsigned *res_size)
Get the raw value of the given attribute value-pair.
Definition avpair.c:1039
char * rc_avpair_log(rc_handle const *rh, VALUE_PAIR *pair, char *buf, size_t buf_len)
Format a sequence of attribute value pairs into a printable string.
Definition avpair.c:954
VALUE_PAIR * rc_avpair_next(VALUE_PAIR *t)
Iterates through the attribute-value pairs.
Definition avpair.c:113
int rc_avpair_get_uint32(VALUE_PAIR *vp, uint32_t *res)
Get the integer value of the given attribute value-pair.
Definition avpair.c:986
int rc_avpair_get_in6(VALUE_PAIR *vp, struct in6_addr *res, unsigned *prefix)
Get the IPv6 address and prefix value of the given attribute value-pair.
Definition avpair.c:1007
void rc_avpair_get_attr(VALUE_PAIR *vp, unsigned *type, unsigned *id)
Get the attribute ID and type of the given attribute value-pair.
Definition avpair.c:1059
VALUE_PAIR * rc_avpair_gen(rc_handle const *rh, VALUE_PAIR *pair, unsigned char const *ptr, int length, uint32_t vendorspec)
Decode a raw RADIUS attribute buffer into a VALUE_PAIR list.
Definition avpair.c:444
void rc_avpair_free(VALUE_PAIR *pair)
Frees all value_pairs in the list.
Definition avpair.c:569
VALUE_PAIR * rc_avpair_copy(VALUE_PAIR *p)
Return a copy of the existing list "p" ala strdup().
Definition avpair.c:482
int rc_avpair_tostr(rc_handle const *rh, VALUE_PAIR *pair, char *name, int ln, char *value, int lv)
Translate an av_pair into printable strings.
Definition avpair.c:838
int rc_avpair_assign(VALUE_PAIR *vp, void const *pval, int len)
Assigns the given value to an attribute-value pair.
Definition avpair.c:136
int rc_avpair_parse(rc_handle const *rh, char const *buffer, VALUE_PAIR **first_pair)
Parses the buffer to extract the attribute-value pairs.
Definition avpair.c:631
VALUE_PAIR * rc_avpair_add(rc_handle const *rh, VALUE_PAIR **list, uint32_t attrid, void const *pval, int len, uint32_t vendorspec)
Adds an attribute-value pair to the given list.
Definition avpair.c:47
void rc_avpair_insert(VALUE_PAIR **a, VALUE_PAIR *p, VALUE_PAIR *b)
Insert a VALUE_PAIR into a list.
Definition avpair.c:517
VALUE_PAIR * rc_avpair_get(VALUE_PAIR *vp, uint32_t attrid, uint32_t vendorspec)
Find the first attribute value-pair (which matches the given attribute) from the specified value-pair...
Definition avpair.c:465
VALUE_PAIR * rc_avpair_new(rc_handle const *rh, uint32_t attrid, void const *pval, int len, uint32_t vendorspec)
Make a new attribute-value pair with given parameters.
Definition avpair.c:197
@ PW_TYPE_IPADDR
The attribute is an IPv4 address in host-byte order.
Definition radcli.h:130
@ PW_TYPE_IPV6ADDR
The attribute is an 128-bit IPv6 address.
Definition radcli.h:132
@ PW_TYPE_IPV6PREFIX
The attribute is an IPv6 prefix; the lvalue will indicate its size.
Definition radcli.h:133
@ PW_TYPE_INTEGER
The attribute is a 32-bit integer.
Definition radcli.h:129
@ PW_TYPE_DATE
The attribute contains a 32-bit number indicating the seconds since epoch.
Definition radcli.h:131
@ PW_TYPE_STRING
The attribute is a printable string.
Definition radcli.h:128
rc_attr_type type
attribute type.
Definition radcli.h:258
uint64_t attribute
attribute numeric value of type rc_attr_id including vendor; use VENDOR() and ATTRID() to separate.
Definition radcli.h:257
uint32_t lvalue
attribute value if type is PW_TYPE_INTEGER, PW_TYPE_DATE or PW_TYPE_IPADDR.
Definition radcli.h:259
char strvalue[AUTH_STRING_LEN+1]
contains attribute value in other cases.
Definition radcli.h:260
char name[RC_NAME_LENGTH+1]
attribute name if known.
Definition radcli.h:256