add new RADIUS client library
[radsecproxy.git] / lib / radius / print.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 print.c
29  *  \brief Functions to print things.
30  */
31
32 #include <networkradius-devel/client.h>
33 #include <string.h>
34 #ifdef NR_TYPE_IPV6ADDR
35 #include <arpa/inet.h>
36 #endif
37
38 #ifndef NDEBUG
39 void nr_packet_print_hex(RADIUS_PACKET *packet)
40 {
41         int i;
42
43         if (!packet->data) return;
44
45         printf("  Code:\t\t%u\n", packet->data[0]);
46         printf("  Id:\t\t%u\n", packet->data[1]);
47         printf("  Length:\t%u\n", ((packet->data[2] << 8) |
48                                    (packet->data[3])));
49         printf("  Vector:\t");
50         for (i = 4; i < 20; i++) {
51                 printf("%02x", packet->data[i]);
52         }
53         printf("\n");
54         if ((packet->flags & NR_PACKET_SIGNED) == 0) printf("\t\tWARNING: nr_packet_sign() was not called!\n");
55
56         if (packet->length > 20) {
57                 int total;
58                 const uint8_t *ptr;
59                 printf("  Data:");
60
61                 total = packet->length - 20;
62                 ptr = packet->data + 20;
63
64                 while (total > 0) {
65                         int attrlen;
66
67                         printf("\t\t");
68                         if (total < 2) { /* too short */
69                                 printf("%02x\n", *ptr);
70                                 break;
71                         }
72
73                         if (ptr[1] > total) { /* too long */
74                                 for (i = 0; i < total; i++) {
75                                         printf("%02x ", ptr[i]);
76                                 }
77                                 break;
78                         }
79
80                         printf("%02x  %02x  ", ptr[0], ptr[1]);
81                         attrlen = ptr[1] - 2;
82                         ptr += 2;
83                         total -= 2;
84
85                         for (i = 0; i < attrlen; i++) {
86                                 if ((i > 0) && ((i & 0x0f) == 0x00))
87                                         printf("\t\t\t");
88                                 printf("%02x ", ptr[i]);
89                                 if ((i & 0x0f) == 0x0f) printf("\n");
90                         }
91
92                         if (!attrlen || ((attrlen & 0x0f) != 0x00)) printf("\n");
93
94                         ptr += attrlen;
95                         total -= attrlen;
96                 }
97         }
98         printf("\n");
99         fflush(stdout);
100 }
101 #endif
102
103 size_t nr_vp_snprintf_value(char *buffer, size_t buflen, const VALUE_PAIR *vp)
104 {
105         size_t i, len;
106         char *p = buffer;
107
108         switch (vp->da->type) {
109         case NR_TYPE_STRING:
110                 /*
111                  *      FIXME: escape backslash && quotes!
112                  */
113                 len = snprintf(p, buflen, "\"%s\"", vp->vp_strvalue);
114                 break;
115
116         case NR_TYPE_DATE:
117         case NR_TYPE_INTEGER:
118         case NR_TYPE_SHORT:
119         case NR_TYPE_BYTE:
120                 len = snprintf(p, buflen, "%u", vp->vp_integer);
121                 break;
122
123         case NR_TYPE_IPADDR:
124                 len = snprintf(p, buflen, "%u.%u.%u.%u",
125                                (vp->vp_ipaddr >> 24) & 0xff,
126                                (vp->vp_ipaddr >> 16) & 0xff,
127                                (vp->vp_ipaddr >> 8) & 0xff,
128                                vp->vp_ipaddr & 0xff);
129                 break;
130
131 #ifdef NR_TYPE_IPV6ADDR
132         case NR_TYPE_IPV6ADDR:
133                 if (!inet_ntop(AF_INET6, &vp->vp_ipv6addr, buffer, buflen)) {
134                         return -NR_ERR_SYSTEM;
135                 }
136                 break;
137 #endif
138
139 #ifdef NR_TYPE_IFID
140         case NR_TYPE_IFID:
141                 len = snprintf(p, buflen, "%02x%02x%02x%02x%02x%02x%02x%02x",
142                                vp->vp_ifid[0], vp->vp_ifid[1],
143                                vp->vp_ifid[2], vp->vp_ifid[3],
144                                vp->vp_ifid[4], vp->vp_ifid[5],
145                                vp->vp_ifid[6], vp->vp_ifid[7]);
146                 break;
147 #endif
148
149         case NR_TYPE_OCTETS:
150                 len = snprintf(p, buflen, "0x");
151                 if (len >= buflen) return 0;
152
153                 p += len;
154                 buflen -= len;
155
156                 for (i = 0; i < vp->length; i++) {
157                         len = snprintf(p, buflen, "%02x", vp->vp_octets[i]);
158                         if (len >= buflen) return 0;
159                         
160                         p += len;
161                         buflen -= len;
162                 }
163                 len = 0;
164                 break;
165
166         default:
167                 break;
168         }
169
170         if (len >= buflen) return 0;
171
172         p += len;
173         buflen -= len;
174
175         return p - buffer;
176 }
177
178 size_t nr_vp_snprintf(char *buffer, size_t buflen, const VALUE_PAIR *vp)
179 {
180         size_t len;
181         char *p = buffer;
182
183         len = snprintf(p, buflen, "%s = ", vp->da->name);
184         if (len >= buflen) return 0;
185
186         p += len;
187         buflen -= len;
188
189         len = nr_vp_snprintf_value(p, buflen, vp);
190         if (len == 0) return 0;
191
192         if (len >= buflen) return 0;
193
194         p += len;
195
196         return p - buffer;
197 }
198
199 #ifndef NDEBUG
200 void nr_vp_fprintf_list(FILE *fp, const VALUE_PAIR *vps)
201 {
202         const VALUE_PAIR *vp;
203         char buffer[1024];
204
205         for (vp = vps; vp != NULL; vp = vp->next) {
206                 nr_vp_snprintf(buffer, sizeof(buffer), vp);
207                 fprintf(fp, "\t%s\n", buffer);
208         }
209 }
210 #endif
211
212 /** \cond PRIVATE */
213 #define NR_STRERROR_BUFSIZE (1024)
214 static char nr_strerror_buffer[NR_STRERROR_BUFSIZE];
215
216 void nr_strerror_printf(const char *fmt, ...)
217 {
218         va_list ap;
219         va_start(ap, fmt);
220         vsnprintf(nr_strerror_buffer, sizeof(nr_strerror_buffer), fmt, ap);
221         va_end(ap);
222
223         fprintf(stderr, "ERROR: %s\n", nr_strerror_buffer);
224 }
225 /** \endcond */
226
227 const char *nr_strerror(int error)
228 {
229         if (error == 0) return nr_strerror_buffer;
230
231         if (error < 0) error = -error;
232
233         switch (error) {
234         default: return "Unknown error";
235         case NR_ERR_SYSTEM: return strerror(errno);
236
237         case NR_ERR_INVALID_ARG: return "Invalid argument";
238         case NR_ERR_PACKET_TOO_SMALL: return "Packet is too small";
239         case NR_ERR_PACKET_TOO_LARGE: return "Packet is too large";
240         case NR_ERR_ATTR_OVERFLOW: return "Attribute overflows packet";
241         case NR_ERR_ATTR_TOO_SMALL: return "Attribute is too small";
242         case NR_ERR_ATTR_TOO_LARGE: return "Attribute is too large";
243         case NR_ERR_ATTR_UNKNOWN: return "Unknown attribute";
244         case NR_ERR_ATTR_BAD_NAME: return "Invalid name for attribute";
245         case NR_ERR_ATTR_VALUE_MALFORMED: return "Invalid value for attribute";
246         case NR_ERR_ATTR_INVALID: return "Invalid attribute";
247         case NR_ERR_TOO_MANY_ATTRS: return "Too many attributes in the packet";
248         case NR_ERR_ATTR_TYPE_UNKNOWN: return "Attribute type unknown";
249         case NR_ERR_MSG_AUTH_LEN: return "Invalid Message-Authenticator";
250         case NR_ERR_MSG_AUTH_WRONG: return "Incorrect Message-Authenticator";
251         case NR_ERR_REQUEST_REQUIRED: return "Request is required";
252         case NR_ERR_REQUEST_CODE_INVALID: return "Invalid request code";
253         case NR_ERR_AUTH_VECTOR_WRONG: return "Incorrect Request Authenticator";
254         case NR_ERR_RESPONSE_CODE_INVALID: return "Response code is unsupported";
255         case NR_ERR_RESPONSE_ID_INVALID: return "Response ID is invalid";
256         case NR_ERR_RESPONSE_SRC_INVALID: return "Response from the wrong src ip/port";
257         case NR_ERR_NO_PACKET_DATA: return "Cannot encode the packet";
258         case NR_ERR_VENDOR_UNKNOWN: return "Vendor is unknown";
259         case NR_ERR_INTERNAL_FAILURE: return "Internal failure";
260         case NR_ERR_UNSUPPORTED: return "Unsupported feature";
261         case NR_ERR_NO_MEM: return "Out of memory";
262         case NR_ERR_IN_USE: return "Resource is in use";
263                 
264         }
265 }