small cleanups
[libradsec.git] / lib / avp.c
1 /* Copyright 2011 PADL Software Pty Ltd. All rights reserved.
2    See the file COPYING for licensing information.  */
3
4 #if defined HAVE_CONFIG_H
5 #include <config.h>
6 #endif
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <stdint.h>
11 #include <string.h>
12 #include <assert.h>
13
14 #include <radsec/radsec.h>
15 #include <radius/client.h>
16
17 #define RS_ERR(err) ((err) < 0 ? -err : RSE_OK)
18
19 void
20 rs_avp_free (rs_avp **vps)
21 {
22   nr_vp_free (vps);
23 }
24
25 size_t
26 rs_avp_length (rs_const_avp *vp)
27 {
28   if (vp == NULL)
29     return 0;
30
31   return vp->length;
32 }
33
34 rs_attr_type_t
35 rs_avp_typeof (rs_const_avp *vp)
36 {
37   if (vp == NULL)
38     return RS_TYPE_INVALID;
39
40   return vp->da->type;
41 }
42
43 void
44 rs_avp_attrid (rs_const_avp *vp,
45                unsigned int *attr,
46                unsigned int *vendor)
47 {
48   assert (vp != NULL);
49
50   *attr = vp->da->attr;
51   *vendor = vp->da->vendor;
52 }
53
54 const char *
55 rs_avp_name (rs_const_avp *vp)
56 {
57   return (vp != NULL) ? vp->da->name : NULL;
58 }
59
60 void
61 rs_avp_append (rs_avp **head, rs_avp *tail)
62 {
63   nr_vps_append (head, tail);
64 }
65
66 rs_avp *
67 rs_avp_find (rs_avp *vp, unsigned int attr, unsigned int vendor)
68 {
69   if (vp == NULL)
70     return NULL;
71
72   return nr_vps_find (vp, attr, vendor);
73 }
74
75 rs_const_avp *
76 rs_avp_find_const (rs_const_avp *vp,
77                    unsigned int attr, unsigned int vendor)
78 {
79   if (vp == NULL)
80     return NULL;
81
82   return nr_vps_find ((rs_avp *)vp, attr, vendor);
83 }
84
85 rs_avp *
86 rs_avp_alloc (unsigned int attr, unsigned int vendor)
87 {
88   const DICT_ATTR *da;
89   VALUE_PAIR *vp;
90
91   da = nr_dict_attr_byvalue (attr, vendor);
92   if (da == NULL) {
93     vp = nr_vp_alloc_raw (attr, vendor);
94   } else {
95     vp = nr_vp_alloc (da);
96   }
97
98   if (vp == NULL)
99     return NULL;
100
101   return vp;
102 }
103
104 rs_avp *
105 rs_avp_dup (rs_const_avp *vp)
106 {
107   rs_avp *vp2;
108
109   vp2 = nr_vp_alloc (vp->da);
110   if (vp2 == NULL)
111     return NULL;
112
113   vp2->length = vp->length;
114   vp2->tag = vp->tag;
115   vp2->next = NULL;
116
117 #ifdef RS_TYPE_TLV
118   if (rs_avp_is_tlv (vp)) {
119     vp2->vp_tlv = malloc (vp->length);
120     if (vp2->vp_tlv == NULL) {
121       rs_avp_free (vp2);
122       return NULL;
123     }
124     memcpy (vp2->vp_tlv, vp->vp_tlv, vp->length);
125     return vp2;
126   }
127 #endif
128
129   memcpy (vp2->vp_strvalue, vp->vp_strvalue, vp->length);
130   if (rs_avp_is_string (vp))
131     vp2->vp_strvalue[vp->length] = '\0';
132
133   return vp2;
134 }
135
136 rs_avp *
137 rs_avp_next (rs_avp *vp)
138 {
139   return (vp != NULL) ? vp->next : NULL;
140 }
141
142 rs_const_avp *
143 rs_avp_next_const (rs_const_avp *vp)
144 {
145   return (vp != NULL) ? vp->next : NULL;
146 }
147
148 int
149 rs_avp_delete (rs_avp **first,
150                unsigned int attr, unsigned int vendor)
151 {
152   int found = 0;
153   rs_avp **p;
154
155   for (p = first; *p != NULL; p++) {
156     if ((*p)->da->attr == attr &&
157         (*p)->da->vendor == vendor) {
158       rs_avp *next = (*p)->next;
159
160       (*p)->next = NULL;
161       rs_avp_free (p);
162
163       *p = next;
164       found++;
165     }
166   }
167
168   return found ? RSE_OK : RSE_ATTR_UNKNOWN;
169 }
170
171 const char *
172 rs_avp_string_value (rs_const_avp *vp)
173 {
174   if (!rs_avp_is_string (vp))
175     return NULL;
176
177   return vp->vp_strvalue;
178 }
179
180 int
181 rs_avp_string_set (rs_avp *vp, const char *str)
182 {
183   int err;
184
185   if (vp == NULL)
186     return RSE_INVAL;
187   if (!rs_avp_is_string (vp))
188     return RSE_ATTR_INVALID;
189
190   err = nr_vp_set_data (vp, str, strlen (str));
191   return RS_ERR(err);
192 }
193
194 uint32_t
195 rs_avp_integer_value (rs_const_avp *vp)
196 {
197   if (!rs_avp_is_integer (vp))
198     return 0;
199   return vp->vp_integer;
200 }
201
202 int
203 rs_avp_integer_set (rs_avp *vp, uint32_t val)
204 {
205   int err;
206
207   if (vp == NULL)
208     return RSE_INVAL;
209   if (!rs_avp_is_integer (vp))
210     return RSE_ATTR_INVALID;
211
212   err = nr_vp_set_data (vp, &val, sizeof (val));
213   return RS_ERR(err);
214 }
215
216 uint32_t
217 rs_avp_ipaddr_value (rs_const_avp *vp)
218 {
219   if (!rs_avp_is_ipaddr (vp))
220     return 0;
221   return vp->vp_ipaddr;
222 }
223
224 int
225 rs_avp_ipaddr_set (rs_avp *vp, struct in_addr in)
226 {
227   int err;
228
229   if (vp == NULL)
230     return RSE_INVAL;
231   if (!rs_avp_is_ipaddr (vp))
232     return RSE_ATTR_INVALID;
233
234   err = nr_vp_set_data (vp, &in, sizeof (in));
235   return RS_ERR(err);
236 }
237
238 time_t
239 rs_avp_date_value (rs_const_avp *vp)
240 {
241   if (!rs_avp_is_date (vp))
242     return 0;
243   return vp->vp_date;
244 }
245
246 int
247 rs_avp_date_set (rs_avp *vp, time_t date)
248 {
249   uint32_t date32;
250   int err;
251
252   if (vp == NULL)
253     return RSE_INVAL;
254   if (!rs_avp_is_date (vp))
255     return RSE_ATTR_INVALID;
256   if (date > 0xFFFFFFFF)
257     return RSE_ATTR_INVALID;
258
259   date32 = (uint32_t)date;
260   err = nr_vp_set_data (vp, &date32, sizeof (date32));
261
262   return RS_ERR(err);
263 }
264
265 const unsigned char *
266 rs_avp_octets_value_const_ptr (rs_const_avp *vp)
267 {
268   return rs_avp_octets_value_ptr ((rs_avp *)vp);
269 }
270
271 unsigned char *
272 rs_avp_octets_value_ptr (rs_avp *vp)
273 {
274   if (vp == NULL)
275     return NULL;
276
277 #ifdef RS_TYPE_TLV
278   if (rs_avp_is_tlv (vp))
279     return vp->vp_tlv;
280 #endif
281
282   return vp->vp_octets;
283 }
284
285 int
286 rs_avp_octets_value_byref (rs_avp *vp,
287                            unsigned char **p,
288                            size_t *len)
289 {
290   if (vp == NULL)
291     return RSE_INVAL;
292
293   *len = vp->length;
294   *p = (unsigned char *)rs_avp_octets_value_ptr (vp);
295
296   return RSE_OK;
297 }
298
299 int
300 rs_avp_octets_value (rs_const_avp *vp,
301                      unsigned char *buf,
302                      size_t *len)
303 {
304   if (vp == NULL)
305     return RSE_INVAL;
306
307   if (vp->length > *len) {
308     *len = vp->length;
309     return RSE_ATTR_TOO_SMALL;
310   }
311
312   *len = vp->length;
313
314 #ifdef RS_TYPE_TLV
315   if (rs_avp_is_tlv (vp))
316     memcpy (buf, vp->vp_tlv, vp->length);
317   else
318 #endif
319     memcpy (buf, vp->vp_octets, vp->length);
320
321   return RSE_OK;
322 }
323
324 int
325 rs_avp_fragmented_value (rs_const_avp *vps,
326                          unsigned char *buf,
327                          size_t *len)
328 {
329   size_t total_len = 0;
330   unsigned char *p;
331   rs_const_avp *vp;
332
333   if (vps == NULL)
334     return RSE_INVAL;
335
336   if (!rs_avp_is_octets (vps) &&
337       !rs_avp_is_string (vps))
338     return RSE_ATTR_INVALID;
339
340   for (vp = vps;
341        vp != NULL;
342        vp = rs_avp_find_const (vp->next, vp->da->attr, vp->da->vendor))
343     total_len += vp->length;
344
345   if (*len < total_len) {
346     *len = total_len;
347     return RSE_ATTR_TOO_SMALL;
348   }
349
350   for (vp = vps, p = buf;
351        vp != NULL;
352        vp = rs_avp_find_const (vp->next, vp->da->attr, vp->da->vendor)) {
353     memcpy (p, vp->vp_octets, vp->length);
354     p += vp->length;
355   }
356
357   *len = total_len;
358
359   return RSE_OK;
360 }
361
362 int
363 rs_avp_octets_set (rs_avp *vp,
364                    const unsigned char *buf,
365                    size_t len)
366 {
367   int err;
368
369   if (!rs_avp_is_octets (vp))
370     return RSE_ATTR_INVALID;
371
372   err = nr_vp_set_data (vp, buf, len);
373
374   return RS_ERR(err);
375 }
376
377 int
378 rs_avp_ifid_value (rs_const_avp *vp, uint8_t val[8])
379 {
380   if (!rs_avp_is_ifid (vp))
381     return RSE_ATTR_INVALID;
382
383   memcpy (val, vp->vp_ifid, 8);
384
385   return RSE_OK;
386 }
387
388 int
389 rs_avp_ifid_set (rs_avp *vp, const uint8_t val[8])
390 {
391   int err;
392
393   if (!rs_avp_is_ifid (vp))
394     return RSE_ATTR_INVALID;
395
396   err = nr_vp_set_data (vp, val, 8);
397   return RS_ERR(err);
398 }
399
400 uint8_t
401 rs_avp_byte_value (rs_const_avp *vp)
402 {
403   if (!rs_avp_is_byte (vp))
404     return 0;
405   return vp->vp_integer;
406 }
407
408 int
409 rs_avp_byte_set (rs_avp *vp, uint8_t val)
410 {
411   int err;
412
413   if (!rs_avp_is_byte (vp))
414     return RSE_ATTR_INVALID;
415
416   err = nr_vp_set_data (vp, &val, sizeof (val));
417   return RS_ERR(err);
418 }
419
420 uint16_t
421 rs_avp_short_value (rs_const_avp *vp)
422 {
423   if (!rs_avp_is_short (vp))
424     return 0;
425   return vp->vp_integer;
426 }
427
428 int
429 rs_avp_short_set (rs_avp *vp, uint16_t val)
430 {
431   int err;
432
433   if (!rs_avp_is_short (vp))
434     return RSE_ATTR_INVALID;
435
436   err = nr_vp_set_data (vp, &val, sizeof (val));
437   return RS_ERR(err);
438 }
439
440 int
441 rs_attr_find (const char *name,
442               unsigned int *attr,
443               unsigned int *vendor)
444 {
445   const DICT_ATTR *da;
446
447   da = nr_dict_attr_byname (name);
448   if (da == NULL)
449     return RSE_ATTR_UNKNOWN;
450
451   *attr = da->attr;
452   *vendor = da->vendor;
453
454   return RSE_OK;
455 }
456
457 int
458 rs_attr_display_name (unsigned int attr,
459                       unsigned int vendor,
460                       char *buffer,
461                       size_t bufsize,
462                       int canonical)
463 {
464   const DICT_ATTR *da = NULL;
465   DICT_ATTR da2;
466   int err;
467
468   if (!canonical) {
469     da = nr_dict_attr_byvalue (attr, vendor);
470   }
471   if (da == NULL) {
472     err = nr_dict_attr_2struct(&da2, attr, vendor,
473                                buffer, bufsize);
474     if (err < 0)
475       return -err;
476   } else {
477     snprintf(buffer, bufsize, "%s", da->name);
478   }
479
480   return RSE_OK;
481 }
482
483 int
484 rs_attr_parse_name (const char *name,
485                     unsigned int *attr,
486                     unsigned int *vendor)
487 {
488   const DICT_ATTR *da;
489
490   if (strncmp(name, "Attr-", 5) == 0) {
491     char *s = (char *)&name[5];
492     unsigned int tmp;
493
494     tmp = strtoul(s, &s, 10);
495     if (*s == '.') {
496       s++;
497
498       switch (tmp) {
499       case PW_VENDOR_SPECIFIC:
500         *vendor = strtoul(s, &s, 10);
501         if (*s != '.')
502           return RSE_ATTR_BAD_NAME;
503
504         s++;
505
506         *attr = strtoul(s, &s, 10);
507         if (*s != '\0')
508           return RSE_ATTR_BAD_NAME;
509
510         break;
511       default:
512         return RSE_ATTR_BAD_NAME;
513       }
514     } else {
515       *attr = tmp;
516       *vendor = 0;
517     }
518   } else {
519     da = nr_dict_attr_byname (name);
520     if (da == NULL)
521       return RSE_ATTR_UNKNOWN;
522
523     *attr = da->attr;
524     *vendor = da->vendor;
525   }
526
527   return RSE_OK;
528 }
529
530 size_t
531 rs_avp_display_value (rs_const_avp *vp,
532                       char *buffer,
533                       size_t buflen)
534 {
535   return nr_vp_snprintf_value (buffer, buflen, vp);
536 }
537