don't return in void function
[radsecproxy.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   assert (vp != NULL);
29   return vp->length;
30 }
31
32 rs_attr_type_t
33 rs_avp_typeof (rs_const_avp *vp)
34 {
35   return vp ? vp->da->type : RS_TYPE_INVALID;
36 }
37
38 void
39 rs_avp_attrid (rs_const_avp *vp,
40                unsigned int *attr,
41                unsigned int *vendor)
42 {
43   *attr = vp->da->attr;
44   *vendor = vp->da->vendor;
45 }
46
47 const char *
48 rs_avp_name (rs_const_avp *vp)
49 {
50   return vp ? vp->da->name : NULL;
51 }
52
53 void
54 rs_avp_append (rs_avp **head, rs_avp *tail)
55 {
56   nr_vps_append (head, tail);
57 }
58
59 rs_avp *
60 rs_avp_find (rs_avp *vp, unsigned int attr, unsigned int vendor)
61 {
62   if (vp == NULL)
63     return NULL;
64
65   return nr_vps_find (vp, attr, vendor);
66 }
67
68 rs_const_avp *
69 rs_avp_find_const (rs_const_avp *vp,
70                    unsigned int attr, unsigned int vendor)
71 {
72   if (vp == NULL)
73     return NULL;
74
75   return nr_vps_find ((rs_avp *)vp, attr, vendor);
76 }
77
78 rs_avp *
79 rs_avp_alloc (unsigned int attr, unsigned int vendor)
80 {
81   const DICT_ATTR *da;
82   VALUE_PAIR *vp;
83
84   da = nr_dict_attr_byvalue (attr, vendor);
85   if (da == NULL) {
86     vp = nr_vp_alloc_raw (attr, vendor);
87   } else {
88     vp = nr_vp_alloc (da);
89   }
90
91   if (vp == NULL)
92     return NULL;
93
94   return vp;
95 }
96
97 rs_avp *
98 rs_avp_dup (rs_const_avp *vp)
99 {
100   rs_avp *vp2;
101
102   vp2 = nr_vp_alloc (vp->da);
103   if (vp2 == NULL)
104     return NULL;
105
106   vp2->length = vp->length;
107   vp2->tag = vp->tag;
108   vp2->next = NULL;
109
110 #ifdef RS_TYPE_TLV
111   if (rs_avp_is_tlv (vp)) {
112     vp2->vp_tlv = malloc (vp->length);
113     if (vp2->vp_tlv == NULL) {
114       rs_avp_free (vp2);
115       return NULL;
116     }
117     memcpy (vp2->vp_tlv, vp->vp_tlv, vp->length);
118     return vp2;
119   }
120 #endif
121
122   memcpy (vp2->vp_strvalue, vp->vp_strvalue, vp->length);
123   if (rs_avp_is_string (vp))
124     vp2->vp_strvalue[vp->length] = '\0';
125
126   return vp2;
127 }
128
129 rs_avp *
130 rs_avp_next (rs_avp *avp)
131 {
132   return avp ? avp->next : NULL;
133 }
134
135 rs_const_avp *
136 rs_avp_next_const (rs_const_avp *avp)
137 {
138   return avp ? avp->next : NULL;
139 }
140
141 int
142 rs_avp_delete (rs_avp **first,
143                unsigned int attr, unsigned int vendor)
144 {
145   int found = 0;
146   rs_avp **p;
147
148   for (p = first; *p != NULL; p++) {
149     if ((*p)->da->attr == attr &&
150         (*p)->da->vendor == vendor) {
151       rs_avp *next = (*p)->next;
152
153       (*p)->next = NULL;
154       rs_avp_free (p);
155
156       *p = next;
157       found++;
158     }
159   }
160
161   return found ? RSE_OK : RSE_ATTR_UNKNOWN;
162 }
163
164 const char *
165 rs_avp_string_value (rs_const_avp *vp)
166 {
167   if (!rs_avp_is_string (vp))
168     return NULL;
169
170   return vp->vp_strvalue;
171 }
172
173 int
174 rs_avp_string_set (rs_avp *vp, const char *str)
175 {
176   int err;
177
178   if (vp == NULL)
179     return RSE_INVAL;
180   if (!rs_avp_is_string (vp))
181     return RSE_ATTR_INVALID;
182
183   err = nr_vp_set_data (vp, str, strlen (str));
184   return RS_ERR(err);
185 }
186
187 uint32_t
188 rs_avp_integer_value (rs_const_avp *vp)
189 {
190   if (!rs_avp_is_integer (vp))
191     return 0;
192   return vp->vp_integer;
193 }
194
195 int
196 rs_avp_integer_set (rs_avp *vp, uint32_t val)
197 {
198   int err;
199
200   if (vp == NULL)
201     return RSE_INVAL;
202   if (!rs_avp_is_integer (vp))
203     return RSE_ATTR_INVALID;
204
205   err = nr_vp_set_data (vp, &val, sizeof (val));
206   return RS_ERR(err);
207 }
208
209 uint32_t
210 rs_avp_ipaddr_value (rs_const_avp *vp)
211 {
212   if (!rs_avp_is_ipaddr (vp))
213     return 0;
214   return vp->vp_ipaddr;
215 }
216
217 int
218 rs_avp_ipaddr_set (rs_avp *vp, struct in_addr in)
219 {
220   int err;
221
222   if (vp == NULL)
223     return RSE_INVAL;
224   if (!rs_avp_is_ipaddr (vp))
225     return RSE_ATTR_INVALID;
226
227   err = nr_vp_set_data (vp, &in, sizeof (in));
228   return RS_ERR(err);
229 }
230
231 time_t
232 rs_avp_date_value (rs_const_avp *vp)
233 {
234   if (!rs_avp_is_date (vp))
235     return 0;
236   return vp->vp_date;
237 }
238
239 int
240 rs_avp_date_set (rs_avp *vp, time_t date)
241 {
242   uint32_t date32;
243   int err;
244
245   if (vp == NULL)
246     return RSE_INVAL;
247   if (!rs_avp_is_date (vp))
248     return RSE_ATTR_INVALID;
249   if (date > 0xFFFFFFFF)
250     return RSE_ATTR_INVALID;
251
252   date32 = (uint32_t)date;
253   err = nr_vp_set_data (vp, &date32, sizeof (date32));
254
255   return RS_ERR(err);
256 }
257
258 const unsigned char *
259 rs_avp_octets_value_const_ptr (rs_const_avp *vp)
260 {
261   return rs_avp_octets_value_ptr ((rs_avp *)vp);
262 }
263
264 unsigned char *
265 rs_avp_octets_value_ptr (rs_avp *vp)
266 {
267   if (vp == NULL)
268     return NULL;
269
270 #ifdef RS_TYPE_TLV
271   if (rs_avp_is_tlv (vp))
272     return vp->vp_tlv;
273 #endif
274
275   return vp->vp_octets;
276 }
277
278 int
279 rs_avp_octets_value_byref (rs_avp *vp,
280                            unsigned char **p,
281                            size_t *len)
282 {
283   if (vp == NULL)
284     return RSE_INVAL;
285
286   *len = vp->length;
287   *p = (unsigned char *)rs_avp_octets_value_ptr (vp);
288
289   return RSE_OK;
290 }
291
292 int
293 rs_avp_octets_value (rs_const_avp *vp,
294                      unsigned char *buf,
295                      size_t *len)
296 {
297   if (vp == NULL)
298     return RSE_INVAL;
299
300   if (vp->length > *len) {
301     *len = vp->length;
302     return RSE_ATTR_TOO_SMALL;
303   }
304
305   *len = vp->length;
306
307 #ifdef RS_TYPE_TLV
308   if (rs_avp_is_tlv (vp))
309     memcpy (buf, vp->vp_tlv, vp->length);
310   else
311 #endif
312     memcpy (buf, vp->vp_octets, vp->length);
313
314   return RSE_OK;
315 }
316
317 int
318 rs_avp_fragmented_value (rs_const_avp *vps,
319                          unsigned char *buf,
320                          size_t *len)
321 {
322   size_t total_len = 0;
323   unsigned char *p;
324   rs_const_avp *vp;
325
326   if (vps == NULL)
327     return RSE_INVAL;
328
329   if (!rs_avp_is_octets (vps) &&
330       !rs_avp_is_string (vps))
331     return RSE_ATTR_INVALID;
332
333   for (vp = vps;
334        vp != NULL;
335        vp = rs_avp_find_const (vp->next, vp->da->attr, vp->da->vendor))
336     total_len += vp->length;
337
338   if (*len < total_len) {
339     *len = total_len;
340     return RSE_ATTR_TOO_SMALL;
341   }
342
343   for (vp = vps, p = buf;
344        vp != NULL;
345        vp = rs_avp_find_const (vp->next, vp->da->attr, vp->da->vendor)) {
346     memcpy (p, vp->vp_octets, vp->length);
347     p += vp->length;
348   }
349
350   *len = total_len;
351
352   return RSE_OK;
353 }
354
355 int
356 rs_avp_octets_set (rs_avp *vp,
357                    const unsigned char *buf,
358                    size_t len)
359 {
360   int err;
361
362   if (!rs_avp_is_octets (vp))
363     return RSE_ATTR_INVALID;
364
365   err = nr_vp_set_data (vp, buf, len);
366
367   return RS_ERR(err);
368 }
369
370 int
371 rs_avp_ifid_value (rs_const_avp *vp, uint8_t val[8])
372 {
373   if (!rs_avp_is_ifid (vp))
374     return RSE_ATTR_INVALID;
375
376   memcpy (val, vp->vp_ifid, 8);
377
378   return RSE_OK;
379 }
380
381 int
382 rs_avp_ifid_set (rs_avp *vp, const uint8_t val[8])
383 {
384   int err;
385
386   if (!rs_avp_is_ifid (vp))
387     return RSE_ATTR_INVALID;
388
389   err = nr_vp_set_data (vp, val, 8);
390   return RS_ERR(err);
391 }
392
393 uint8_t
394 rs_avp_byte_value (rs_const_avp *vp)
395 {
396   if (!rs_avp_is_byte (vp))
397     return 0;
398   return vp->vp_integer;
399 }
400
401 int
402 rs_avp_byte_set (rs_avp *vp, uint8_t val)
403 {
404   int err;
405
406   if (!rs_avp_is_byte (vp))
407     return RSE_ATTR_INVALID;
408
409   err = nr_vp_set_data (vp, &val, sizeof (val));
410   return RS_ERR(err);
411 }
412
413 uint16_t
414 rs_avp_short_value (rs_const_avp *vp)
415 {
416   if (!rs_avp_is_short (vp))
417     return 0;
418   return vp->vp_integer;
419 }
420
421 int
422 rs_avp_short_set (rs_avp *vp, uint16_t val)
423 {
424   int err;
425
426   if (!rs_avp_is_short (vp))
427     return RSE_ATTR_INVALID;
428
429   err = nr_vp_set_data (vp, &val, sizeof (val));
430   return RS_ERR(err);
431 }
432
433 int
434 rs_attr_find (const char *name,
435               unsigned int *attr,
436               unsigned int *vendor)
437 {
438   const DICT_ATTR *da;
439
440   da = nr_dict_attr_byname (name);
441   if (da == NULL)
442     return RSE_ATTR_UNKNOWN;
443
444   *attr = da->attr;
445   *vendor = da->vendor;
446
447   return RSE_OK;
448 }
449
450 size_t
451 rs_avp_display_value (rs_const_avp *vp,
452                       char *buffer,
453                       size_t buflen)
454 {
455   return nr_vp_snprintf_value (buffer, buflen, vp);
456 }