add new RADIUS client library
[radsecproxy.git] / lib / radius / parse.c
1 /*
2 Copyright (c) 2011, Network RADIUS SARL
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7     * Redistributions of source code must retain the above copyright
8       notice, this list of conditions and the following disclaimer.
9     * Redistributions in binary form must reproduce the above copyright
10       notice, this list of conditions and the following disclaimer in the
11       documentation and/or other materials provided with the distribution.
12     * Neither the name of the <organization> nor the
13       names of its contributors may be used to endorse or promote products
14       derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 /** \file parse.c
29  *  \brief Routines to parse strings into internal data structures
30  */
31
32 #include <networkradius-devel/client.h>
33 #include <arpa/inet.h>
34
35 ssize_t nr_vp_sscanf_value(VALUE_PAIR *vp, const char *value)
36 {
37         char *end;
38
39         switch (vp->da->type) {
40         case NR_TYPE_STRING:
41                 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
42                 vp->length = strlen(vp->vp_strvalue);
43                 return vp->length;
44
45         case NR_TYPE_DATE:
46         case NR_TYPE_INTEGER:
47                 vp->vp_integer = strtoul(value, &end, 10);
48                 if ((value == end) || (*end != '\0')) {
49                         nr_debug_error("Invalid value");
50                         return -NR_ERR_ATTR_VALUE_MALFORMED;
51                 }
52                 return (end - value);
53
54         case NR_TYPE_IPADDR:
55                 if (inet_pton(AF_INET, value, &vp->vp_ipaddr) < 0) {
56                         return -NR_ERR_SYSTEM;
57                 }
58                 return strlen(value);
59                 
60 #ifdef NR_TYPE_IPV6ADDR
61         case NR_TYPE_IPV6ADDR:
62                 if (inet_pton(AF_INET6, value, &vp-vp>ipv6addr) < 0) {
63                         return -NR_ERR_SYSTEM;
64                 }
65                 return strlen(value);
66 #endif
67
68 #ifdef NR_TYPE_IFID
69         case NR_TYPE_IFID:
70         {
71                 int i, array[8];
72
73                 if (sscanf(value, "%02x%02x%02x%02x%02x%02x%02x%02x",
74                            &array[0], &array[1], &array[2], &array[3],
75                            &array[4], &array[5], &array[6], &array[7]) != 8) {
76                         return -NR_ERR_SYSTEM;
77                 }
78
79                 for (i = 0; i < 8; i++) vp->vp_ifid[i] = array[i] & 0xff;
80
81         }
82                 break;
83 #endif
84
85         default:
86                 nr_debug_error("Invalid type");
87                 return -NR_ERR_ATTR_TYPE_UNKNOWN;
88         }
89
90         return 0;
91 }
92
93 int nr_vp_sscanf(const char *string, VALUE_PAIR **pvp)
94 {
95         int rcode;
96         const char *p;
97         char *q;
98         const DICT_ATTR *da;
99         VALUE_PAIR *vp;
100         char buffer[256];
101
102         if (!string || !pvp) return -NR_ERR_INVALID_ARG;
103
104         p = string;
105         q = buffer;
106         while (*p && (*p != ' ') && (*p != '=')) {
107                 *(q++) = *(p++);
108         }
109         *q = '\0';
110
111         if (q == buffer) {
112                 nr_debug_error("No Attribute name");
113                 return -NR_ERR_ATTR_BAD_NAME;
114         }
115
116         da = nr_dict_attr_byname(buffer);
117         if (!da) {
118                 nr_debug_error("Unknown attribute \"%s\"", buffer);
119                 return -NR_ERR_ATTR_UNKNOWN;
120         }
121
122         while (*p == ' ') p++;
123         if (*p != '=') {
124                 nr_debug_error("Unexpected text after attribute name");
125                 return -NR_ERR_ATTR_BAD_NAME;
126         }
127
128         p++;
129         while (*p == ' ') p++;
130
131         vp = nr_vp_alloc(da);
132         if (!vp) return -NR_ERR_NO_MEM;
133
134         rcode = nr_vp_sscanf_value(vp, p);
135         if (rcode < 0) {
136                 nr_vp_free(&vp);
137                 return rcode;
138         }
139
140         *pvp = vp;
141         return 0;
142 }