/* $OpenBSD: radiusd_standard.c,v 1.6 2024/07/02 00:33:51 yasuoka Exp $ */ /* * Copyright (c) 2013, 2023 Internet Initiative Japan Inc. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "radiusd.h" #include "radiusd_module.h" TAILQ_HEAD(attrs,attr); struct attr { uint8_t type; uint32_t vendor; uint32_t vtype; TAILQ_ENTRY(attr) next; }; struct module_standard { struct module_base *base; bool strip_atmark_realm; bool strip_nt_domain; struct attrs remove_reqattrs; struct attrs remove_resattrs; }; struct radius_const_str { const unsigned constval; const char *label; }; static void radius_const_print(FILE *, RADIUS_PACKET *, uint8_t, const char *, struct radius_const_str *); static void module_standard_config_set(void *, const char *, int, char * const *); static void module_standard_reqdeco(void *, u_int, const u_char *, size_t); static void module_standard_resdeco(void *, u_int, const u_char *, size_t, const u_char *, size_t); static void module_accounting_request(void *, u_int, const u_char *, size_t); static void radius_u32_print(FILE *, RADIUS_PACKET *, uint8_t, const char *); static void radius_str_print(FILE *, RADIUS_PACKET *, uint8_t, const char *); static void radius_ipv4_print(FILE *, RADIUS_PACKET *, uint8_t, const char *); static void radius_ipv6_print(FILE *, RADIUS_PACKET *, uint8_t, const char *); static struct radius_const_str nas_port_type_consts[], tunnel_type_consts[], service_type_consts[], framed_protocol_consts[], acct_status_type_consts[], acct_authentic_consts[], terminate_cause_consts[], tunnel_medium_type_consts[]; int main(int argc, char *argv[]) { struct module_standard module_standard; struct module_handlers handlers = { .config_set = module_standard_config_set, .request_decoration = module_standard_reqdeco, .response_decoration = module_standard_resdeco, .accounting_request = module_accounting_request }; struct attr *attr; memset(&module_standard, 0, sizeof(module_standard)); TAILQ_INIT(&module_standard.remove_reqattrs); TAILQ_INIT(&module_standard.remove_resattrs); if ((module_standard.base = module_create( STDIN_FILENO, &module_standard, &handlers)) == NULL) err(1, "Could not create a module instance"); module_drop_privilege(module_standard.base, 0); if (pledge("stdio", NULL) == -1) err(1, "pledge"); module_load(module_standard.base); openlog(NULL, LOG_PID, LOG_DAEMON); while (module_run(module_standard.base) == 0) ; module_destroy(module_standard.base); while ((attr = TAILQ_FIRST(&module_standard.remove_reqattrs)) != NULL) { TAILQ_REMOVE(&module_standard.remove_reqattrs, attr, next); freezero(attr, sizeof(struct attr)); } while ((attr = TAILQ_FIRST(&module_standard.remove_resattrs)) != NULL) { TAILQ_REMOVE(&module_standard.remove_resattrs, attr, next); freezero(attr, sizeof(struct attr)); } exit(EXIT_SUCCESS); } static void module_standard_config_set(void *ctx, const char *name, int argc, char * const * argv) { struct module_standard *module = ctx; struct attr *attr; const char *errmsg = "none"; const char *errstr; if (strcmp(name, "strip-atmark-realm") == 0) { SYNTAX_ASSERT(argc == 1, "`strip-atmark-realm' must have only one argment"); if (strcmp(argv[0], "true") == 0) module->strip_atmark_realm = true; else if (strcmp(argv[0], "false") == 0) module->strip_atmark_realm = false; else SYNTAX_ASSERT(0, "`strip-atmark-realm' must `true' or `false'"); } else if (strcmp(name, "strip-nt-domain") == 0) { SYNTAX_ASSERT(argc == 1, "`strip-nt-domain' must have only one argment"); if (strcmp(argv[0], "true") == 0) module->strip_nt_domain = true; else if (strcmp(argv[0], "false") == 0) module->strip_nt_domain = false; else SYNTAX_ASSERT(0, "`strip-nt-domain' must `true' or `false'"); } else if (strcmp(name, "remove-request-attribute") == 0 || strcmp(name, "remove-response-attribute") == 0) { struct attrs *attrs; if (strcmp(name, "remove-request-attribute") == 0) { SYNTAX_ASSERT(argc == 1 || argc == 2, "`remove-request-attribute' must have one or two " "argment"); attrs = &module->remove_reqattrs; } else { SYNTAX_ASSERT(argc == 1 || argc == 2, "`remove-response-attribute' must have one or two " "argment"); attrs = &module->remove_resattrs; } if ((attr = calloc(1, sizeof(struct attr))) == NULL) { module_send_message(module->base, IMSG_NG, "Out of memory: %s", strerror(errno)); } if (argc == 1) { attr->type = strtonum(argv[0], 0, 255, &errstr); if (errstr == NULL && attr->type != RADIUS_TYPE_VENDOR_SPECIFIC) { TAILQ_INSERT_TAIL(attrs, attr, next); attr = NULL; } } else { attr->type = RADIUS_TYPE_VENDOR_SPECIFIC; attr->vendor = strtonum(argv[0], 0, UINT32_MAX, &errstr); if (errstr == NULL) attr->vtype = strtonum(argv[1], 0, 255, &errstr); if (errstr == NULL) { TAILQ_INSERT_TAIL(attrs, attr, next); attr = NULL; } } freezero(attr, sizeof(struct attr)); if (strcmp(name, "remove-request-attribute") == 0) SYNTAX_ASSERT(attr == NULL, "wrong number for `remove-request-attribute`"); else SYNTAX_ASSERT(attr == NULL, "wrong number for `remove-response-attribute`"); } else if (strncmp(name, "_", 1) == 0) /* nothing */; /* ignore all internal messages */ else { module_send_message(module->base, IMSG_NG, "Unknown config parameter name `%s'", name); return; } module_send_message(module->base, IMSG_OK, NULL); return; syntax_error: module_send_message(module->base, IMSG_NG, "%s", errmsg); } /* request message decoration */ static void module_standard_reqdeco(void *ctx, u_int q_id, const u_char *pkt, size_t pktlen) { struct module_standard *module = ctx; RADIUS_PACKET *radpkt = NULL; int changed = 0; char *ch, *username, buf[256]; struct attr *attr; if (module->strip_atmark_realm || module->strip_nt_domain) { if ((radpkt = radius_convert_packet(pkt, pktlen)) == NULL) { syslog(LOG_ERR, "%s: radius_convert_packet() failed: %m", __func__); module_stop(module->base); return; } username = buf; if (radius_get_string_attr(radpkt, RADIUS_TYPE_USER_NAME, username, sizeof(buf)) != 0) { syslog(LOG_WARNING, "standard: q=%u could not get User-Name attribute", q_id); goto skip; } if (module->strip_atmark_realm && (ch = strrchr(username, '@')) != NULL) { *ch = '\0'; changed++; } if (module->strip_nt_domain && (ch = strchr(username, '\\')) != NULL) { username = ch + 1; changed++; } if (changed > 0) { radius_del_attr_all(radpkt, RADIUS_TYPE_USER_NAME); radius_put_string_attr(radpkt, RADIUS_TYPE_USER_NAME, username); } } skip: TAILQ_FOREACH(attr, &module->remove_reqattrs, next) { if (radpkt == NULL && (radpkt = radius_convert_packet(pkt, pktlen)) == NULL) { syslog(LOG_ERR, "%s: radius_convert_packet() failed: %m", __func__); module_stop(module->base); return; } if (attr->type != RADIUS_TYPE_VENDOR_SPECIFIC) radius_del_attr_all(radpkt, attr->type); else radius_del_vs_attr_all(radpkt, attr->vendor, attr->vtype); } if (radpkt == NULL) { pkt = NULL; pktlen = 0; } else { pkt = radius_get_data(radpkt); pktlen = radius_get_length(radpkt); } if (module_reqdeco_done(module->base, q_id, pkt, pktlen) == -1) { syslog(LOG_ERR, "%s: module_reqdeco_done() failed: %m", __func__); module_stop(module->base); } if (radpkt != NULL) radius_delete_packet(radpkt); } /* response message decoration */ 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) { struct module_standard *module = ctx; RADIUS_PACKET *radres = NULL; struct attr *attr; TAILQ_FOREACH(attr, &module->remove_resattrs, next) { if (radres == NULL && (radres = radius_convert_packet(res, reslen)) == NULL) { syslog(LOG_ERR, "%s: radius_convert_packet() failed: %m", __func__); module_stop(module->base); return; } if (attr->type != RADIUS_TYPE_VENDOR_SPECIFIC) radius_del_attr_all(radres, attr->type); else radius_del_vs_attr_all(radres, attr->vendor, attr->vtype); } if (radres == NULL) { res = NULL; reslen = 0; } else { res = radius_get_data(radres); reslen = radius_get_length(radres); } if (module_resdeco_done(module->base, q_id, res, reslen) == -1) { syslog(LOG_ERR, "%s: module_resdeco_done() failed: %m", __func__); module_stop(module->base); } if (radres != NULL) radius_delete_packet(radres); } static void module_accounting_request(void *ctx, u_int query_id, const u_char *pkt, size_t pktlen) { RADIUS_PACKET *radpkt = NULL; struct module_standard *module = ctx; FILE *fp; char *buf = NULL; size_t size = 0; if ((radpkt = radius_convert_packet(pkt, pktlen)) == NULL) { syslog(LOG_ERR, "%s: radius_convert_packet() failed: %m", __func__); module_stop(module->base); return; } if ((fp = open_memstream(&buf, &size)) == NULL) { syslog(LOG_ERR, "%s: open_memstream() failed: %m", __func__); module_stop(module->base); goto out; } radius_const_print(fp, radpkt, RADIUS_TYPE_ACCT_STATUS_TYPE, "Acct-Status-Type", acct_status_type_consts); radius_ipv4_print(fp, radpkt, RADIUS_TYPE_NAS_IP_ADDRESS, "NAS-IP-Address"); radius_ipv6_print(fp, radpkt, RADIUS_TYPE_NAS_IPV6_ADDRESS, "NAS-IPv6-Address"); radius_const_print(fp, radpkt, RADIUS_TYPE_NAS_PORT_TYPE, "NAS-Port-Type", nas_port_type_consts); radius_u32_print(fp, radpkt, RADIUS_TYPE_NAS_PORT, "NAS-Port"); radius_str_print(fp, radpkt, RADIUS_TYPE_NAS_IDENTIFIER, "NAS-Identifier"); radius_str_print(fp, radpkt, RADIUS_TYPE_CALLING_STATION_ID, "Calling-Station-ID"); radius_str_print(fp, radpkt, RADIUS_TYPE_CALLED_STATION_ID, "Called-Station-ID"); radius_const_print(fp, radpkt, RADIUS_TYPE_TUNNEL_MEDIUM_TYPE, "Tunnel-Medium-Type", tunnel_medium_type_consts); radius_str_print(fp, radpkt, RADIUS_TYPE_TUNNEL_CLIENT_ENDPOINT, "Tunnel-Client-Endpoint"); radius_str_print(fp, radpkt, RADIUS_TYPE_TUNNEL_SERVER_ENDPOINT, "Tunnel-Server-Endpoint"); radius_str_print(fp, radpkt, RADIUS_TYPE_TUNNEL_ASSIGNMENT_ID, "Tunnel-Assignment-ID"); radius_str_print(fp, radpkt, RADIUS_TYPE_ACCT_TUNNEL_CONNECTION, "Acct-Tunnel-Connection"); radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_SESSION_TIME, "Acct-Session-Time"); radius_const_print(fp, radpkt, RADIUS_TYPE_TUNNEL_TYPE, "Tunnel-Type", tunnel_type_consts); radius_str_print(fp, radpkt, RADIUS_TYPE_USER_NAME, "User-Name"); radius_const_print(fp, radpkt, RADIUS_TYPE_SERVICE_TYPE, "Service-Type", service_type_consts); radius_const_print(fp, radpkt, RADIUS_TYPE_FRAMED_PROTOCOL, "Framed-Protocol", framed_protocol_consts); radius_ipv4_print(fp, radpkt, RADIUS_TYPE_FRAMED_IP_ADDRESS, "Framed-IP-Address"); radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_DELAY_TIME, "Acct-Delay-Time"); radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_INPUT_OCTETS, "Acct-Input-Octets"); radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_OUTPUT_OCTETS, "Acct-Output-Octets"); radius_str_print(fp, radpkt, RADIUS_TYPE_ACCT_SESSION_ID, "Acct-Session-ID"); radius_const_print(fp, radpkt, RADIUS_TYPE_ACCT_AUTHENTIC, "Acct-Authentic", acct_authentic_consts); radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_SESSION_TIME, "Acct-Sesion-Time"); radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_INPUT_PACKETS, "Acct-Input-Packets"); radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_OUTPUT_PACKETS, "Acct-Output-Packets"); radius_const_print(fp, radpkt, RADIUS_TYPE_ACCT_TERMINATE_CAUSE, "Acct-Terminate-Cause", terminate_cause_consts); radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_INPUT_GIGAWORDS, "Acct-Input-Gigawords"); radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_OUTPUT_GIGAWORDS, "Acct-Output-Gigawords"); fputc('\0', fp); fclose(fp); syslog(LOG_INFO, "Accounting q=%u %s", query_id, buf + 1); out: radius_delete_packet(radpkt); freezero(buf, size); } /*********************************************************************** * print RADIUS attribute ***********************************************************************/ static void radius_const_print(FILE *fout, RADIUS_PACKET *radpkt, uint8_t attr_type, const char *attr_name, struct radius_const_str *consts) { struct radius_const_str *const_; uint32_t u32val; if (radius_get_uint32_attr(radpkt, attr_type, &u32val) != 0) return; for (const_ = consts; const_->label != NULL; const_++) { if (const_->constval == u32val) break; } fprintf(fout, " %s=%s(%u)", attr_name, (const_ != NULL)? const_->label : "unknown", (unsigned)u32val); } static void radius_u32_print(FILE *fout, RADIUS_PACKET *radpkt, uint8_t attr_type, const char *attr_name) { uint32_t u32val; if (radius_get_uint32_attr(radpkt, attr_type, &u32val) != 0) return; fprintf(fout, " %s=%u", attr_name, u32val); } static void radius_str_print(FILE *fout, RADIUS_PACKET *radpkt, uint8_t attr_type, const char *attr_name) { char strval[256]; if (radius_get_string_attr(radpkt, attr_type, strval, sizeof(strval)) != 0) return; fprintf(fout, " %s=%s", attr_name, strval); } static void radius_ipv4_print(FILE *fout, RADIUS_PACKET *radpkt, uint8_t attr_type, const char *attr_name) { struct in_addr ipv4; char buf[128]; if (radius_get_ipv4_attr(radpkt, attr_type, &ipv4) != 0) return; fprintf(fout, " %s=%s", attr_name, inet_ntop(AF_INET, &ipv4, buf, sizeof(buf))); } static void radius_ipv6_print(FILE *fout, RADIUS_PACKET *radpkt, uint8_t attr_type, const char *attr_name) { struct in6_addr ipv6; char buf[128]; if (radius_get_ipv6_attr(radpkt, attr_type, &ipv6) != 0) return; fprintf(fout, " %s=%s", attr_name, inet_ntop(AF_INET6, &ipv6, buf, sizeof(buf))); } static struct radius_const_str nas_port_type_consts[] = { { RADIUS_NAS_PORT_TYPE_ASYNC, "\"Async\"" }, { RADIUS_NAS_PORT_TYPE_SYNC, "\"Sync\"" }, { RADIUS_NAS_PORT_TYPE_ISDN_SYNC, "\"ISDN Sync\"" }, { RADIUS_NAS_PORT_TYPE_ISDN_ASYNC_V120, "\"ISDN Async V.120\"" }, { RADIUS_NAS_PORT_TYPE_ISDN_ASYNC_V110, "\"ISDN Async V.110\"" }, { RADIUS_NAS_PORT_TYPE_VIRTUAL, "\"Virtual\"" }, { RADIUS_NAS_PORT_TYPE_PIAFS, "\"PIAFS\"" }, { RADIUS_NAS_PORT_TYPE_HDLC_CLEAR_CHANNEL, "\"HDLC Clear Channel\"" }, { RADIUS_NAS_PORT_TYPE_X_25, "\"X.25\"" }, { RADIUS_NAS_PORT_TYPE_X_75, "\"X.75\"" }, { RADIUS_NAS_PORT_TYPE_G3_FAX, "\"G.3 Fax\"" }, { RADIUS_NAS_PORT_TYPE_SDSL, "\"SDSL\"" }, { RADIUS_NAS_PORT_TYPE_ADSL_CAP, "\"ADSL-CAP\"" }, { RADIUS_NAS_PORT_TYPE_ADSL_DMT, "\"ADSL-DMT\"" }, { RADIUS_NAS_PORT_TYPE_IDSL, "\"IDSL\"" }, { RADIUS_NAS_PORT_TYPE_ETHERNET, "\"Ethernet\"" }, { RADIUS_NAS_PORT_TYPE_XDSL, "\"xDSL\"" }, { RADIUS_NAS_PORT_TYPE_CABLE, "\"Cable\"" }, { RADIUS_NAS_PORT_TYPE_WIRELESS, "\"Wireless\"" }, { RADIUS_NAS_PORT_TYPE_WIRELESS_802_11, "\"Wireless - IEEE 802.11\"" }, { 0, NULL } }; static struct radius_const_str tunnel_type_consts[] = { { RADIUS_TUNNEL_TYPE_PPTP, "PPTP" }, { RADIUS_TUNNEL_TYPE_L2F, "L2F" }, { RADIUS_TUNNEL_TYPE_L2TP, "L2TP" }, { RADIUS_TUNNEL_TYPE_ATMP, "ATMP" }, { RADIUS_TUNNEL_TYPE_VTP, "VTP" }, { RADIUS_TUNNEL_TYPE_AH, "AH" }, { RADIUS_TUNNEL_TYPE_IP, "IP" }, { RADIUS_TUNNEL_TYPE_MOBILE, "MIN-IP-IP" }, { RADIUS_TUNNEL_TYPE_ESP, "ESP" }, { RADIUS_TUNNEL_TYPE_GRE, "GRE" }, { RADIUS_TUNNEL_TYPE_VDS, "DVS" }, { 0, NULL } }; static struct radius_const_str service_type_consts[] = { { RADIUS_SERVICE_TYPE_LOGIN, "\"Login\"" }, { RADIUS_SERVICE_TYPE_FRAMED, "\"Framed\"" }, { RADIUS_SERVICE_TYPE_CB_LOGIN, "\"Callback Login\"" }, { RADIUS_SERVICE_TYPE_CB_FRAMED, "\"Callback Framed\"" }, { RADIUS_SERVICE_TYPE_OUTBOUND, "\"Outbound\"" }, { RADIUS_SERVICE_TYPE_ADMINISTRATIVE, "\"Administrative\"" }, { RADIUS_SERVICE_TYPE_NAS_PROMPT, "\"NAS Propmt\"" }, /* there had been a typo in radius.h */ #if !defined(RADIUS_SERVICE_TYPE_CB_NAS_PROMPT) && \ defined(RADIUS_SERVICE_TYPE_CB_NAS_PROMPTi) #define RADIUS_SERVICE_TYPE_CB_NAS_PROMPT RADIUS_SERVICE_TYPE_CB_NAS_PROMPTi #endif { RADIUS_SERVICE_TYPE_AUTHENTICAT_ONLY, "\"Authenticat Only\"" }, { RADIUS_SERVICE_TYPE_CB_NAS_PROMPT, "\"Callback NAS Prompt\"" }, { RADIUS_SERVICE_TYPE_CALL_CHECK, "\"Call Check\"" }, { RADIUS_SERVICE_TYPE_CB_ADMINISTRATIVE, "\"Callback Administrative\"" }, { 0, NULL } }; static struct radius_const_str framed_protocol_consts[] = { { RADIUS_FRAMED_PROTOCOL_PPP, "PPP" }, { RADIUS_FRAMED_PROTOCOL_SLIP, "SLIP" }, { RADIUS_FRAMED_PROTOCOL_ARAP, "ARAP" }, { RADIUS_FRAMED_PROTOCOL_GANDALF, "Gandalf" }, { RADIUS_FRAMED_PROTOCOL_XYLOGICS, "Xylogics" }, { RADIUS_FRAMED_PROTOCOL_X75, "X.75" }, { 0, NULL } }; static struct radius_const_str acct_status_type_consts[] = { { RADIUS_ACCT_STATUS_TYPE_START, "Start" }, { RADIUS_ACCT_STATUS_TYPE_STOP, "Stop" }, { RADIUS_ACCT_STATUS_TYPE_INTERIM_UPDATE, "Interim-Update" }, { RADIUS_ACCT_STATUS_TYPE_ACCT_ON, "Accounting-On" }, { RADIUS_ACCT_STATUS_TYPE_ACCT_OFF, "Accounting-Off" }, { 0, NULL } }; static struct radius_const_str acct_authentic_consts[] = { { RADIUS_ACCT_AUTHENTIC_RADIUS, "RADIUS" }, { RADIUS_ACCT_AUTHENTIC_LOCAL, "Local" }, { RADIUS_ACCT_AUTHENTIC_REMOTE, "Remote" }, { 0, NULL } }; static struct radius_const_str terminate_cause_consts[] = { { RADIUS_TERMNATE_CAUSE_USER_REQUEST, "\"User Request\"" }, { RADIUS_TERMNATE_CAUSE_LOST_CARRIER, "\"Lost Carrier\"" }, { RADIUS_TERMNATE_CAUSE_LOST_SERVICE, "\"Lost Service\"" }, { RADIUS_TERMNATE_CAUSE_IDLE_TIMEOUT, "\"Idle Timeout\"" }, { RADIUS_TERMNATE_CAUSE_SESSION_TIMEOUT, "\"Session Timeout\"" }, { RADIUS_TERMNATE_CAUSE_ADMIN_RESET, "\"Admin Reset\"" }, { RADIUS_TERMNATE_CAUSE_ADMIN_REBOOT, "\"Admin Reboot\"" }, { RADIUS_TERMNATE_CAUSE_PORT_ERROR, "\"Port Error\"" }, { RADIUS_TERMNATE_CAUSE_NAS_ERROR, "\"NAS Error\"" }, { RADIUS_TERMNATE_CAUSE_NAS_RESET, "\"NAS Request\"" }, { RADIUS_TERMNATE_CAUSE_NAS_REBOOT, "\"NAS Reboot\"" }, { RADIUS_TERMNATE_CAUSE_PORT_UNNEEDED, "\"Port Unneeded\"" }, { RADIUS_TERMNATE_CAUSE_PORT_PREEMPTED, "\"Port Preempted\"" }, { RADIUS_TERMNATE_CAUSE_PORT_SUSPENDED, "\"Port Suspended\"" }, { RADIUS_TERMNATE_CAUSE_SERVICE_UNAVAIL, "\"Service Unavailable\"" }, { RADIUS_TERMNATE_CAUSE_CALLBACK, "\"Callback\"" }, { RADIUS_TERMNATE_CAUSE_USER_ERROR, "\"User Error\"" }, { RADIUS_TERMNATE_CAUSE_HOST_REQUEST, "\"Host Request\"" }, { 0, NULL } }; static struct radius_const_str tunnel_medium_type_consts[] = { { RADIUS_TUNNEL_MEDIUM_TYPE_IPV4, "IPv4" }, { RADIUS_TUNNEL_MEDIUM_TYPE_IPV6, "IPv6" }, { RADIUS_TUNNEL_MEDIUM_TYPE_NSAP, "NSAP" }, { RADIUS_TUNNEL_MEDIUM_TYPE_HDLC, "HDLC" }, { RADIUS_TUNNEL_MEDIUM_TYPE_BBN1822, "BBN1822" }, { RADIUS_TUNNEL_MEDIUM_TYPE_802, "802" }, { RADIUS_TUNNEL_MEDIUM_TYPE_E163, "E.163" }, { RADIUS_TUNNEL_MEDIUM_TYPE_E164, "E.164" }, { 0, NULL } };