1 /*	$OpenBSD: radiusd_standard.c,v 1.6 2024/07/02 00:33:51 yasuoka Exp $	*/
2 
3 /*
4  * Copyright (c) 2013, 2023 Internet Initiative Japan Inc.
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 #include <sys/types.h>
19 #include <sys/queue.h>
20 #include <netinet/in.h>
21 #include <arpa/inet.h>
22 
23 #include <err.h>
24 #include <errno.h>
25 #include <radius.h>
26 #include <stdbool.h>
27 #include <stdint.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <syslog.h>
32 #include <unistd.h>
33 
34 #include "radiusd.h"
35 #include "radiusd_module.h"
36 
37 TAILQ_HEAD(attrs,attr);
38 
39 struct attr {
40 	uint8_t			 type;
41 	uint32_t		 vendor;
42 	uint32_t		 vtype;
43 	TAILQ_ENTRY(attr)	 next;
44 };
45 
46 struct module_standard {
47 	struct module_base	*base;
48 	bool			 strip_atmark_realm;
49 	bool			 strip_nt_domain;
50 	struct attrs		 remove_reqattrs;
51 	struct attrs		 remove_resattrs;
52 };
53 
54 struct radius_const_str {
55 	const unsigned	 constval;
56 	const char	*label;
57 };
58 
59 static void	 radius_const_print(FILE *, RADIUS_PACKET *, uint8_t,
60 		    const char *, struct radius_const_str *);
61 static void	 module_standard_config_set(void *, const char *, int,
62 		    char * const *);
63 static void	 module_standard_reqdeco(void *, u_int, const u_char *, size_t);
64 static void	 module_standard_resdeco(void *, u_int, const u_char *, size_t,
65 		    const u_char *, size_t);
66 static void	 module_accounting_request(void *, u_int, const u_char *,
67 		    size_t);
68 static void	 radius_u32_print(FILE *, RADIUS_PACKET *, uint8_t,
69 		    const char *);
70 static void	 radius_str_print(FILE *, RADIUS_PACKET *, uint8_t,
71 		    const char *);
72 static void	 radius_ipv4_print(FILE *, RADIUS_PACKET *, uint8_t,
73 		    const char *);
74 static void	 radius_ipv6_print(FILE *, RADIUS_PACKET *, uint8_t,
75 		    const char *);
76 
77 static struct radius_const_str
78 		 nas_port_type_consts[], tunnel_type_consts[],
79 		 service_type_consts[], framed_protocol_consts[],
80 		 acct_status_type_consts[], acct_authentic_consts[],
81 		 terminate_cause_consts[], tunnel_medium_type_consts[];
82 
83 int
main(int argc,char * argv[])84 main(int argc, char *argv[])
85 {
86 	struct module_standard module_standard;
87 	struct module_handlers handlers = {
88 		.config_set = module_standard_config_set,
89 		.request_decoration = module_standard_reqdeco,
90 		.response_decoration = module_standard_resdeco,
91 		.accounting_request = module_accounting_request
92 	};
93 	struct attr		*attr;
94 
95 	memset(&module_standard, 0, sizeof(module_standard));
96 	TAILQ_INIT(&module_standard.remove_reqattrs);
97 	TAILQ_INIT(&module_standard.remove_resattrs);
98 
99 	if ((module_standard.base = module_create(
100 	    STDIN_FILENO, &module_standard, &handlers)) == NULL)
101 		err(1, "Could not create a module instance");
102 
103 	module_drop_privilege(module_standard.base, 0);
104 	if (pledge("stdio", NULL) == -1)
105 		err(1, "pledge");
106 
107 	module_load(module_standard.base);
108 
109 	openlog(NULL, LOG_PID, LOG_DAEMON);
110 
111 	while (module_run(module_standard.base) == 0)
112 		;
113 
114 	module_destroy(module_standard.base);
115 	while ((attr = TAILQ_FIRST(&module_standard.remove_reqattrs)) != NULL) {
116 		TAILQ_REMOVE(&module_standard.remove_reqattrs, attr, next);
117 		freezero(attr, sizeof(struct attr));
118 	}
119 	while ((attr = TAILQ_FIRST(&module_standard.remove_resattrs)) != NULL) {
120 		TAILQ_REMOVE(&module_standard.remove_resattrs, attr, next);
121 		freezero(attr, sizeof(struct attr));
122 	}
123 
124 	exit(EXIT_SUCCESS);
125 }
126 
127 static void
module_standard_config_set(void * ctx,const char * name,int argc,char * const * argv)128 module_standard_config_set(void *ctx, const char *name, int argc,
129     char * const * argv)
130 {
131 	struct module_standard	*module = ctx;
132 	struct attr		*attr;
133 	const char		*errmsg = "none";
134 	const char		*errstr;
135 
136 	if (strcmp(name, "strip-atmark-realm") == 0) {
137 		SYNTAX_ASSERT(argc == 1,
138 		    "`strip-atmark-realm' must have only one argment");
139 		if (strcmp(argv[0], "true") == 0)
140 			module->strip_atmark_realm = true;
141 		else if (strcmp(argv[0], "false") == 0)
142 			module->strip_atmark_realm = false;
143 		else
144 			SYNTAX_ASSERT(0,
145 			    "`strip-atmark-realm' must `true' or `false'");
146 	} else if (strcmp(name, "strip-nt-domain") == 0) {
147 		SYNTAX_ASSERT(argc == 1,
148 		    "`strip-nt-domain' must have only one argment");
149 		if (strcmp(argv[0], "true") == 0)
150 			module->strip_nt_domain = true;
151 		else if (strcmp(argv[0], "false") == 0)
152 			module->strip_nt_domain = false;
153 		else
154 			SYNTAX_ASSERT(0,
155 			    "`strip-nt-domain' must `true' or `false'");
156 	} else if (strcmp(name, "remove-request-attribute") == 0 ||
157 	    strcmp(name, "remove-response-attribute") == 0) {
158 		struct attrs		*attrs;
159 
160 		if (strcmp(name, "remove-request-attribute") == 0) {
161 			SYNTAX_ASSERT(argc == 1 || argc == 2,
162 			    "`remove-request-attribute' must have one or two "
163 			    "argment");
164 			attrs = &module->remove_reqattrs;
165 		} else {
166 			SYNTAX_ASSERT(argc == 1 || argc == 2,
167 			    "`remove-response-attribute' must have one or two "
168 			    "argment");
169 			attrs = &module->remove_resattrs;
170 		}
171 		if ((attr = calloc(1, sizeof(struct attr))) == NULL) {
172 			module_send_message(module->base, IMSG_NG,
173 			    "Out of memory: %s", strerror(errno));
174 		}
175 		if (argc == 1) {
176 			attr->type = strtonum(argv[0], 0, 255, &errstr);
177 			if (errstr == NULL &&
178 			    attr->type != RADIUS_TYPE_VENDOR_SPECIFIC) {
179 				TAILQ_INSERT_TAIL(attrs, attr, next);
180 				attr = NULL;
181 			}
182 		} else {
183 			attr->type = RADIUS_TYPE_VENDOR_SPECIFIC;
184 			attr->vendor = strtonum(argv[0], 0, UINT32_MAX,
185 			    &errstr);
186 			if (errstr == NULL)
187 				attr->vtype = strtonum(argv[1], 0, 255,
188 				    &errstr);
189 			if (errstr == NULL) {
190 				TAILQ_INSERT_TAIL(attrs, attr, next);
191 				attr = NULL;
192 			}
193 		}
194 		freezero(attr, sizeof(struct attr));
195 		if (strcmp(name, "remove-request-attribute") == 0)
196 			SYNTAX_ASSERT(attr == NULL,
197 			    "wrong number for `remove-request-attribute`");
198 		else
199 			SYNTAX_ASSERT(attr == NULL,
200 			    "wrong number for `remove-response-attribute`");
201 	} else if (strncmp(name, "_", 1) == 0)
202 		/* nothing */; /* ignore all internal messages */
203 	else {
204 		module_send_message(module->base, IMSG_NG,
205 		    "Unknown config parameter name `%s'", name);
206 		return;
207 	}
208 	module_send_message(module->base, IMSG_OK, NULL);
209 	return;
210 
211  syntax_error:
212 	module_send_message(module->base, IMSG_NG, "%s", errmsg);
213 }
214 
215 /* request message decoration */
216 static void
module_standard_reqdeco(void * ctx,u_int q_id,const u_char * pkt,size_t pktlen)217 module_standard_reqdeco(void *ctx, u_int q_id, const u_char *pkt, size_t pktlen)
218 {
219 	struct module_standard	*module = ctx;
220 	RADIUS_PACKET		*radpkt = NULL;
221 	int			 changed = 0;
222 	char			*ch, *username, buf[256];
223 	struct attr		*attr;
224 
225 	if (module->strip_atmark_realm || module->strip_nt_domain) {
226 		if ((radpkt = radius_convert_packet(pkt, pktlen)) == NULL) {
227 			syslog(LOG_ERR,
228 			    "%s: radius_convert_packet() failed: %m", __func__);
229 			module_stop(module->base);
230 			return;
231 		}
232 
233 		username = buf;
234 		if (radius_get_string_attr(radpkt, RADIUS_TYPE_USER_NAME,
235 		    username, sizeof(buf)) != 0) {
236 			syslog(LOG_WARNING,
237 			    "standard: q=%u could not get User-Name attribute",
238 			    q_id);
239 			goto skip;
240 		}
241 
242 		if (module->strip_atmark_realm &&
243 		    (ch = strrchr(username, '@')) != NULL) {
244 			*ch = '\0';
245 			changed++;
246 		}
247 		if (module->strip_nt_domain &&
248 		    (ch = strchr(username, '\\')) != NULL) {
249 			username = ch + 1;
250 			changed++;
251 		}
252 		if (changed > 0) {
253 			radius_del_attr_all(radpkt, RADIUS_TYPE_USER_NAME);
254 			radius_put_string_attr(radpkt,
255 			    RADIUS_TYPE_USER_NAME, username);
256 		}
257 	}
258  skip:
259 	TAILQ_FOREACH(attr, &module->remove_reqattrs, next) {
260 		if (radpkt == NULL &&
261 		    (radpkt = radius_convert_packet(pkt, pktlen)) == NULL) {
262 			syslog(LOG_ERR,
263 			    "%s: radius_convert_packet() failed: %m", __func__);
264 			module_stop(module->base);
265 			return;
266 		}
267 		if (attr->type != RADIUS_TYPE_VENDOR_SPECIFIC)
268 			radius_del_attr_all(radpkt, attr->type);
269 		else
270 			radius_del_vs_attr_all(radpkt, attr->vendor,
271 			    attr->vtype);
272 	}
273 	if (radpkt == NULL) {
274 		pkt = NULL;
275 		pktlen = 0;
276 	} else {
277 		pkt = radius_get_data(radpkt);
278 		pktlen = radius_get_length(radpkt);
279 	}
280 	if (module_reqdeco_done(module->base, q_id, pkt, pktlen) == -1) {
281 		syslog(LOG_ERR, "%s: module_reqdeco_done() failed: %m",
282 		    __func__);
283 		module_stop(module->base);
284 	}
285 	if (radpkt != NULL)
286 		radius_delete_packet(radpkt);
287 }
288 
289 /* response message decoration */
290 static void
module_standard_resdeco(void * ctx,u_int q_id,const u_char * req,size_t reqlen,const u_char * res,size_t reslen)291 module_standard_resdeco(void *ctx, u_int q_id, const u_char *req, size_t reqlen,
292     const u_char *res, size_t reslen)
293 {
294 	struct module_standard	*module = ctx;
295 	RADIUS_PACKET		*radres = NULL;
296 	struct attr		*attr;
297 
298 	TAILQ_FOREACH(attr, &module->remove_resattrs, next) {
299 		if (radres == NULL &&
300 		    (radres = radius_convert_packet(res, reslen)) == NULL) {
301 			syslog(LOG_ERR,
302 			    "%s: radius_convert_packet() failed: %m", __func__);
303 			module_stop(module->base);
304 			return;
305 		}
306 		if (attr->type != RADIUS_TYPE_VENDOR_SPECIFIC)
307 			radius_del_attr_all(radres, attr->type);
308 		else
309 			radius_del_vs_attr_all(radres, attr->vendor,
310 			    attr->vtype);
311 	}
312 	if (radres == NULL) {
313 		res = NULL;
314 		reslen = 0;
315 	} else {
316 		res = radius_get_data(radres);
317 		reslen = radius_get_length(radres);
318 	}
319 	if (module_resdeco_done(module->base, q_id, res, reslen) == -1) {
320 		syslog(LOG_ERR, "%s: module_resdeco_done() failed: %m",
321 		    __func__);
322 		module_stop(module->base);
323 	}
324 	if (radres != NULL)
325 		radius_delete_packet(radres);
326 }
327 
328 static void
module_accounting_request(void * ctx,u_int query_id,const u_char * pkt,size_t pktlen)329 module_accounting_request(void *ctx, u_int query_id, const u_char *pkt,
330     size_t pktlen)
331 {
332 	RADIUS_PACKET		*radpkt = NULL;
333 	struct module_standard	*module = ctx;
334 	FILE			*fp;
335 	char			*buf = NULL;
336 	size_t			 size = 0;
337 
338 	if ((radpkt = radius_convert_packet(pkt, pktlen)) == NULL) {
339 		syslog(LOG_ERR,
340 		    "%s: radius_convert_packet() failed: %m", __func__);
341 		module_stop(module->base);
342 		return;
343 	}
344 
345 	if ((fp = open_memstream(&buf, &size)) == NULL) {
346 		syslog(LOG_ERR, "%s: open_memstream() failed: %m", __func__);
347 		module_stop(module->base);
348 		goto out;
349 	}
350 	radius_const_print(fp, radpkt, RADIUS_TYPE_ACCT_STATUS_TYPE,
351 	    "Acct-Status-Type", acct_status_type_consts);
352 
353 	radius_ipv4_print(fp, radpkt, RADIUS_TYPE_NAS_IP_ADDRESS,
354 	    "NAS-IP-Address");
355 	radius_ipv6_print(fp, radpkt, RADIUS_TYPE_NAS_IPV6_ADDRESS,
356 	    "NAS-IPv6-Address");
357 	radius_const_print(fp, radpkt, RADIUS_TYPE_NAS_PORT_TYPE,
358 	    "NAS-Port-Type",  nas_port_type_consts);
359 	radius_u32_print(fp, radpkt, RADIUS_TYPE_NAS_PORT, "NAS-Port");
360 	radius_str_print(fp, radpkt, RADIUS_TYPE_NAS_IDENTIFIER,
361 	    "NAS-Identifier");
362 	radius_str_print(fp, radpkt, RADIUS_TYPE_CALLING_STATION_ID,
363 	    "Calling-Station-ID");
364 	radius_str_print(fp, radpkt, RADIUS_TYPE_CALLED_STATION_ID,
365 	    "Called-Station-ID");
366 
367 	radius_const_print(fp, radpkt, RADIUS_TYPE_TUNNEL_MEDIUM_TYPE,
368 	    "Tunnel-Medium-Type", tunnel_medium_type_consts);
369 	radius_str_print(fp, radpkt, RADIUS_TYPE_TUNNEL_CLIENT_ENDPOINT,
370 	    "Tunnel-Client-Endpoint");
371 	radius_str_print(fp, radpkt, RADIUS_TYPE_TUNNEL_SERVER_ENDPOINT,
372 	    "Tunnel-Server-Endpoint");
373 	radius_str_print(fp, radpkt, RADIUS_TYPE_TUNNEL_ASSIGNMENT_ID,
374 	    "Tunnel-Assignment-ID");
375 	radius_str_print(fp, radpkt, RADIUS_TYPE_ACCT_TUNNEL_CONNECTION,
376 	    "Acct-Tunnel-Connection");
377 
378 	radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_SESSION_TIME,
379 	    "Acct-Session-Time");
380 	radius_const_print(fp, radpkt,
381 	    RADIUS_TYPE_TUNNEL_TYPE, "Tunnel-Type", tunnel_type_consts);
382 	radius_str_print(fp, radpkt, RADIUS_TYPE_USER_NAME, "User-Name");
383 	radius_const_print(fp, radpkt,
384 	    RADIUS_TYPE_SERVICE_TYPE, "Service-Type", service_type_consts);
385 	radius_const_print(fp, radpkt, RADIUS_TYPE_FRAMED_PROTOCOL,
386 	    "Framed-Protocol", framed_protocol_consts);
387 	radius_ipv4_print(fp, radpkt, RADIUS_TYPE_FRAMED_IP_ADDRESS,
388 	    "Framed-IP-Address");
389 	radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_DELAY_TIME,
390 	    "Acct-Delay-Time");
391 	radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_INPUT_OCTETS,
392 	    "Acct-Input-Octets");
393 	radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_OUTPUT_OCTETS,
394 	    "Acct-Output-Octets");
395 	radius_str_print(fp, radpkt, RADIUS_TYPE_ACCT_SESSION_ID,
396 	    "Acct-Session-ID");
397 	radius_const_print(fp, radpkt, RADIUS_TYPE_ACCT_AUTHENTIC,
398 	    "Acct-Authentic", acct_authentic_consts);
399 	radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_SESSION_TIME,
400 	    "Acct-Sesion-Time");
401 	radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_INPUT_PACKETS,
402 	    "Acct-Input-Packets");
403 	radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_OUTPUT_PACKETS,
404 	    "Acct-Output-Packets");
405 	radius_const_print(fp, radpkt, RADIUS_TYPE_ACCT_TERMINATE_CAUSE,
406 	    "Acct-Terminate-Cause", terminate_cause_consts);
407 	radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_INPUT_GIGAWORDS,
408 	    "Acct-Input-Gigawords");
409 	radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_OUTPUT_GIGAWORDS,
410 	    "Acct-Output-Gigawords");
411 
412 	fputc('\0', fp);
413 	fclose(fp);
414 	syslog(LOG_INFO, "Accounting q=%u %s", query_id, buf + 1);
415  out:
416 	radius_delete_packet(radpkt);
417 	freezero(buf, size);
418 }
419 
420 /***********************************************************************
421  * print RADIUS attribute
422  ***********************************************************************/
423 static void
radius_const_print(FILE * fout,RADIUS_PACKET * radpkt,uint8_t attr_type,const char * attr_name,struct radius_const_str * consts)424 radius_const_print(FILE *fout, RADIUS_PACKET *radpkt, uint8_t attr_type,
425     const char *attr_name, struct radius_const_str *consts)
426 {
427 	struct radius_const_str *const_;
428 	uint32_t		 u32val;
429 
430 	if (radius_get_uint32_attr(radpkt, attr_type, &u32val) != 0)
431 		return;
432 
433 	for (const_ = consts; const_->label != NULL; const_++) {
434 		if (const_->constval == u32val)
435 			break;
436 	}
437 
438 	fprintf(fout, " %s=%s(%u)", attr_name, (const_ != NULL)? const_->label
439 	    : "unknown", (unsigned)u32val);
440 }
441 
442 static void
radius_u32_print(FILE * fout,RADIUS_PACKET * radpkt,uint8_t attr_type,const char * attr_name)443 radius_u32_print(FILE *fout, RADIUS_PACKET *radpkt, uint8_t attr_type,
444     const char *attr_name)
445 {
446 	uint32_t		 u32val;
447 
448 	if (radius_get_uint32_attr(radpkt, attr_type, &u32val) != 0)
449 		return;
450 	fprintf(fout, " %s=%u", attr_name, u32val);
451 }
452 
453 static void
radius_str_print(FILE * fout,RADIUS_PACKET * radpkt,uint8_t attr_type,const char * attr_name)454 radius_str_print(FILE *fout, RADIUS_PACKET *radpkt, uint8_t attr_type,
455     const char *attr_name)
456 {
457 	char			 strval[256];
458 
459 	if (radius_get_string_attr(radpkt, attr_type, strval, sizeof(strval))
460 	    != 0)
461 		return;
462 	fprintf(fout, " %s=%s", attr_name, strval);
463 }
464 
465 static void
radius_ipv4_print(FILE * fout,RADIUS_PACKET * radpkt,uint8_t attr_type,const char * attr_name)466 radius_ipv4_print(FILE *fout, RADIUS_PACKET *radpkt, uint8_t attr_type,
467     const char *attr_name)
468 {
469 	struct in_addr		 ipv4;
470 	char			 buf[128];
471 
472 	if (radius_get_ipv4_attr(radpkt, attr_type, &ipv4) != 0)
473 		return;
474 	fprintf(fout, " %s=%s", attr_name,
475 	    inet_ntop(AF_INET, &ipv4, buf, sizeof(buf)));
476 }
477 
478 static void
radius_ipv6_print(FILE * fout,RADIUS_PACKET * radpkt,uint8_t attr_type,const char * attr_name)479 radius_ipv6_print(FILE *fout, RADIUS_PACKET *radpkt, uint8_t attr_type,
480     const char *attr_name)
481 {
482 	struct in6_addr		 ipv6;
483 	char			 buf[128];
484 
485 	if (radius_get_ipv6_attr(radpkt, attr_type, &ipv6) != 0)
486 		return;
487 
488 	fprintf(fout, " %s=%s", attr_name,
489 	    inet_ntop(AF_INET6, &ipv6, buf, sizeof(buf)));
490 }
491 
492 static struct radius_const_str nas_port_type_consts[] = {
493     { RADIUS_NAS_PORT_TYPE_ASYNC,		"\"Async\"" },
494     { RADIUS_NAS_PORT_TYPE_SYNC,		"\"Sync\"" },
495     { RADIUS_NAS_PORT_TYPE_ISDN_SYNC,		"\"ISDN Sync\"" },
496     { RADIUS_NAS_PORT_TYPE_ISDN_ASYNC_V120,	"\"ISDN Async V.120\"" },
497     { RADIUS_NAS_PORT_TYPE_ISDN_ASYNC_V110,	"\"ISDN Async V.110\"" },
498     { RADIUS_NAS_PORT_TYPE_VIRTUAL,		"\"Virtual\"" },
499     { RADIUS_NAS_PORT_TYPE_PIAFS,		"\"PIAFS\"" },
500     { RADIUS_NAS_PORT_TYPE_HDLC_CLEAR_CHANNEL,	"\"HDLC Clear Channel\"" },
501     { RADIUS_NAS_PORT_TYPE_X_25,		"\"X.25\"" },
502     { RADIUS_NAS_PORT_TYPE_X_75,		"\"X.75\"" },
503     { RADIUS_NAS_PORT_TYPE_G3_FAX,		"\"G.3 Fax\"" },
504     { RADIUS_NAS_PORT_TYPE_SDSL,		"\"SDSL\"" },
505     { RADIUS_NAS_PORT_TYPE_ADSL_CAP,		"\"ADSL-CAP\"" },
506     { RADIUS_NAS_PORT_TYPE_ADSL_DMT,		"\"ADSL-DMT\"" },
507     { RADIUS_NAS_PORT_TYPE_IDSL,		"\"IDSL\"" },
508     { RADIUS_NAS_PORT_TYPE_ETHERNET,		"\"Ethernet\"" },
509     { RADIUS_NAS_PORT_TYPE_XDSL,		"\"xDSL\"" },
510     { RADIUS_NAS_PORT_TYPE_CABLE,		"\"Cable\"" },
511     { RADIUS_NAS_PORT_TYPE_WIRELESS,		"\"Wireless\"" },
512     { RADIUS_NAS_PORT_TYPE_WIRELESS_802_11,	"\"Wireless - IEEE 802.11\"" },
513     { 0, NULL }
514 };
515 
516 static struct radius_const_str tunnel_type_consts[] = {
517     { RADIUS_TUNNEL_TYPE_PPTP,		"PPTP" },
518     { RADIUS_TUNNEL_TYPE_L2F,		"L2F" },
519     { RADIUS_TUNNEL_TYPE_L2TP,		"L2TP" },
520     { RADIUS_TUNNEL_TYPE_ATMP,		"ATMP" },
521     { RADIUS_TUNNEL_TYPE_VTP,		"VTP" },
522     { RADIUS_TUNNEL_TYPE_AH,		"AH" },
523     { RADIUS_TUNNEL_TYPE_IP,		"IP" },
524     { RADIUS_TUNNEL_TYPE_MOBILE,	"MIN-IP-IP" },
525     { RADIUS_TUNNEL_TYPE_ESP,		"ESP" },
526     { RADIUS_TUNNEL_TYPE_GRE,		"GRE" },
527     { RADIUS_TUNNEL_TYPE_VDS,		"DVS" },
528     { 0, NULL }
529 };
530 
531 static struct radius_const_str service_type_consts[] = {
532     { RADIUS_SERVICE_TYPE_LOGIN,		"\"Login\"" },
533     { RADIUS_SERVICE_TYPE_FRAMED,		"\"Framed\"" },
534     { RADIUS_SERVICE_TYPE_CB_LOGIN,		"\"Callback Login\"" },
535     { RADIUS_SERVICE_TYPE_CB_FRAMED,		"\"Callback Framed\"" },
536     { RADIUS_SERVICE_TYPE_OUTBOUND,		"\"Outbound\"" },
537     { RADIUS_SERVICE_TYPE_ADMINISTRATIVE,	"\"Administrative\"" },
538     { RADIUS_SERVICE_TYPE_NAS_PROMPT,		"\"NAS Propmt\"" },
539 /* there had been a typo in radius.h */
540 #if !defined(RADIUS_SERVICE_TYPE_CB_NAS_PROMPT) && \
541     defined(RADIUS_SERVICE_TYPE_CB_NAS_PROMPTi)
542 #define RADIUS_SERVICE_TYPE_CB_NAS_PROMPT RADIUS_SERVICE_TYPE_CB_NAS_PROMPTi
543 #endif
544     { RADIUS_SERVICE_TYPE_AUTHENTICAT_ONLY,	"\"Authenticat Only\"" },
545     { RADIUS_SERVICE_TYPE_CB_NAS_PROMPT,	"\"Callback NAS Prompt\"" },
546     { RADIUS_SERVICE_TYPE_CALL_CHECK,		"\"Call Check\"" },
547     { RADIUS_SERVICE_TYPE_CB_ADMINISTRATIVE,	"\"Callback Administrative\"" },
548     { 0, NULL }
549 };
550 
551 static struct radius_const_str framed_protocol_consts[] = {
552     { RADIUS_FRAMED_PROTOCOL_PPP,		"PPP" },
553     { RADIUS_FRAMED_PROTOCOL_SLIP,		"SLIP" },
554     { RADIUS_FRAMED_PROTOCOL_ARAP,		"ARAP" },
555     { RADIUS_FRAMED_PROTOCOL_GANDALF,		"Gandalf" },
556     { RADIUS_FRAMED_PROTOCOL_XYLOGICS,		"Xylogics" },
557     { RADIUS_FRAMED_PROTOCOL_X75,		"X.75" },
558     { 0, NULL }
559 };
560 
561 static struct radius_const_str acct_status_type_consts[] = {
562     { RADIUS_ACCT_STATUS_TYPE_START,		"Start" },
563     { RADIUS_ACCT_STATUS_TYPE_STOP,		"Stop" },
564     { RADIUS_ACCT_STATUS_TYPE_INTERIM_UPDATE,	"Interim-Update" },
565     { RADIUS_ACCT_STATUS_TYPE_ACCT_ON,		"Accounting-On" },
566     { RADIUS_ACCT_STATUS_TYPE_ACCT_OFF,		"Accounting-Off" },
567     { 0, NULL }
568 };
569 
570 static struct radius_const_str acct_authentic_consts[] = {
571     { RADIUS_ACCT_AUTHENTIC_RADIUS,		"RADIUS" },
572     { RADIUS_ACCT_AUTHENTIC_LOCAL,		"Local" },
573     { RADIUS_ACCT_AUTHENTIC_REMOTE,		"Remote" },
574     { 0, NULL }
575 };
576 
577 static struct radius_const_str terminate_cause_consts[] = {
578     { RADIUS_TERMNATE_CAUSE_USER_REQUEST,	"\"User Request\"" },
579     { RADIUS_TERMNATE_CAUSE_LOST_CARRIER,	"\"Lost Carrier\"" },
580     { RADIUS_TERMNATE_CAUSE_LOST_SERVICE,	"\"Lost Service\"" },
581     { RADIUS_TERMNATE_CAUSE_IDLE_TIMEOUT,	"\"Idle Timeout\"" },
582     { RADIUS_TERMNATE_CAUSE_SESSION_TIMEOUT,	"\"Session Timeout\"" },
583     { RADIUS_TERMNATE_CAUSE_ADMIN_RESET,	"\"Admin Reset\"" },
584     { RADIUS_TERMNATE_CAUSE_ADMIN_REBOOT,	"\"Admin Reboot\"" },
585     { RADIUS_TERMNATE_CAUSE_PORT_ERROR,		"\"Port Error\"" },
586     { RADIUS_TERMNATE_CAUSE_NAS_ERROR,		"\"NAS Error\"" },
587     { RADIUS_TERMNATE_CAUSE_NAS_RESET,		"\"NAS Request\"" },
588     { RADIUS_TERMNATE_CAUSE_NAS_REBOOT,		"\"NAS Reboot\"" },
589     { RADIUS_TERMNATE_CAUSE_PORT_UNNEEDED,	"\"Port Unneeded\"" },
590     { RADIUS_TERMNATE_CAUSE_PORT_PREEMPTED,	"\"Port Preempted\"" },
591     { RADIUS_TERMNATE_CAUSE_PORT_SUSPENDED,	"\"Port Suspended\"" },
592     { RADIUS_TERMNATE_CAUSE_SERVICE_UNAVAIL,	"\"Service Unavailable\"" },
593     { RADIUS_TERMNATE_CAUSE_CALLBACK,		"\"Callback\"" },
594     { RADIUS_TERMNATE_CAUSE_USER_ERROR,		"\"User Error\"" },
595     { RADIUS_TERMNATE_CAUSE_HOST_REQUEST,	"\"Host Request\"" },
596     { 0, NULL }
597 };
598 
599 static struct radius_const_str tunnel_medium_type_consts[] = {
600     { RADIUS_TUNNEL_MEDIUM_TYPE_IPV4,		"IPv4" },
601     { RADIUS_TUNNEL_MEDIUM_TYPE_IPV6,		"IPv6" },
602     { RADIUS_TUNNEL_MEDIUM_TYPE_NSAP,		"NSAP" },
603     { RADIUS_TUNNEL_MEDIUM_TYPE_HDLC,		"HDLC" },
604     { RADIUS_TUNNEL_MEDIUM_TYPE_BBN1822,	"BBN1822" },
605     { RADIUS_TUNNEL_MEDIUM_TYPE_802,		"802" },
606     { RADIUS_TUNNEL_MEDIUM_TYPE_E163,		"E.163" },
607     { RADIUS_TUNNEL_MEDIUM_TYPE_E164,		"E.164" },
608     { 0, NULL }
609 };
610