diff --git a/build-root/build-vpp-native/vpp/vnet/dhcp/dhcp.api.h b/build-root/build-vpp-native/vpp/vnet/dhcp/dhcp.api.h new file mode 100644 index 0000000..8f719f2 --- /dev/null +++ b/build-root/build-vpp-native/vpp/vnet/dhcp/dhcp.api.h @@ -0,0 +1,413 @@ +/* + * VLIB API definitions Tue Oct 24 18:42:06 2017 + * Input file: vnet/dhcp/dhcp.api.h + * Automatically generated: please edit the input file NOT this file! + */ + +#if defined(vl_msg_id)||defined(vl_union_id)||defined(vl_printfun) \ + ||defined(vl_endianfun)|| defined(vl_api_version)||defined(vl_typedefs) \ + ||defined(vl_msg_name)||defined(vl_msg_name_crc_list) +/* ok, something was selected */ +#else +#warning no content included from vnet/dhcp/dhcp.api.h +#endif + +#define VL_API_PACKED(x) x __attribute__ ((packed)) + + +/****** Message ID / handler enum ******/ + +#ifdef vl_msg_id +vl_msg_id(VL_API_DHCP_PROXY_CONFIG, vl_api_dhcp_proxy_config_t_handler) +vl_msg_id(VL_API_DHCP_PROXY_CONFIG_REPLY, vl_api_dhcp_proxy_config_reply_t_handler) +vl_msg_id(VL_API_DHCP_PROXY_SET_VSS, vl_api_dhcp_proxy_set_vss_t_handler) +vl_msg_id(VL_API_DHCP_PROXY_SET_VSS_REPLY, vl_api_dhcp_proxy_set_vss_reply_t_handler) +vl_msg_id(VL_API_DHCP_CLIENT_CONFIG, vl_api_dhcp_client_config_t_handler) +vl_msg_id(VL_API_DHCP_CLIENT_CONFIG_REPLY, vl_api_dhcp_client_config_reply_t_handler) +vl_msg_id(VL_API_DHCP_COMPL_EVENT, vl_api_dhcp_compl_event_t_handler) +vl_msg_id(VL_API_DHCP_PROXY_DUMP, vl_api_dhcp_proxy_dump_t_handler) +/* typeonly: dhcp_server */ +vl_msg_id(VL_API_DHCP_PROXY_DETAILS, vl_api_dhcp_proxy_details_t_handler) +#endif + +/****** Message names ******/ + +#ifdef vl_msg_name +vl_msg_name(vl_api_dhcp_proxy_config_t, 1) +vl_msg_name(vl_api_dhcp_proxy_config_reply_t, 1) +vl_msg_name(vl_api_dhcp_proxy_set_vss_t, 1) +vl_msg_name(vl_api_dhcp_proxy_set_vss_reply_t, 1) +vl_msg_name(vl_api_dhcp_client_config_t, 1) +vl_msg_name(vl_api_dhcp_client_config_reply_t, 1) +vl_msg_name(vl_api_dhcp_compl_event_t, 1) +vl_msg_name(vl_api_dhcp_proxy_dump_t, 1) +/* typeonly: dhcp_server */ +vl_msg_name(vl_api_dhcp_proxy_details_t, 1) +#endif + + +/****** Message name, crc list ******/ + +#ifdef vl_msg_name_crc_list +#define foreach_vl_msg_name_crc_dhcp \ +_(VL_API_DHCP_PROXY_CONFIG, dhcp_proxy_config, 3b4f2bc8) \ +_(VL_API_DHCP_PROXY_CONFIG_REPLY, dhcp_proxy_config_reply, fe63196f) \ +_(VL_API_DHCP_PROXY_SET_VSS, dhcp_proxy_set_vss, be54d194) \ +_(VL_API_DHCP_PROXY_SET_VSS_REPLY, dhcp_proxy_set_vss_reply, 5bb4e754) \ +_(VL_API_DHCP_CLIENT_CONFIG, dhcp_client_config, 87920bb6) \ +_(VL_API_DHCP_CLIENT_CONFIG_REPLY, dhcp_client_config_reply, d947f4c8) \ +_(VL_API_DHCP_COMPL_EVENT, dhcp_compl_event, 5218db55) \ +_(VL_API_DHCP_PROXY_DUMP, dhcp_proxy_dump, 175bc073) \ +_(VL_API_DHCP_PROXY_DETAILS, dhcp_proxy_details, 9727dbdd) +#endif + + +/****** Typedefs *****/ + +#ifdef vl_typedefs + +typedef VL_API_PACKED(struct _vl_api_dhcp_proxy_config { + u16 _vl_msg_id; + u32 client_index; + u32 context; + u32 rx_vrf_id; + u32 server_vrf_id; + u8 is_ipv6; + u8 is_add; + u8 dhcp_server[16]; + u8 dhcp_src_address[16]; +}) vl_api_dhcp_proxy_config_t; + +typedef VL_API_PACKED(struct _vl_api_dhcp_proxy_config_reply { + u16 _vl_msg_id; + u32 context; + i32 retval; +}) vl_api_dhcp_proxy_config_reply_t; + +typedef VL_API_PACKED(struct _vl_api_dhcp_proxy_set_vss { + u16 _vl_msg_id; + u32 client_index; + u32 context; + u32 tbl_id; + u32 oui; + u32 fib_id; + u8 is_ipv6; + u8 is_add; +}) vl_api_dhcp_proxy_set_vss_t; + +typedef VL_API_PACKED(struct _vl_api_dhcp_proxy_set_vss_reply { + u16 _vl_msg_id; + u32 context; + i32 retval; +}) vl_api_dhcp_proxy_set_vss_reply_t; + +typedef VL_API_PACKED(struct _vl_api_dhcp_client_config { + u16 _vl_msg_id; + u32 client_index; + u32 context; + u32 sw_if_index; + u8 hostname[64]; + u8 is_add; + u8 want_dhcp_event; + u32 pid; +}) vl_api_dhcp_client_config_t; + +typedef VL_API_PACKED(struct _vl_api_dhcp_client_config_reply { + u16 _vl_msg_id; + u32 context; + i32 retval; +}) vl_api_dhcp_client_config_reply_t; + +typedef VL_API_PACKED(struct _vl_api_dhcp_compl_event { + u16 _vl_msg_id; + u32 client_index; + u32 pid; + u8 hostname[64]; + u8 is_ipv6; + u8 host_address[16]; + u8 router_address[16]; + u8 host_mac[6]; +}) vl_api_dhcp_compl_event_t; + +typedef VL_API_PACKED(struct _vl_api_dhcp_proxy_dump { + u16 _vl_msg_id; + u32 client_index; + u32 context; + u8 is_ip6; +}) vl_api_dhcp_proxy_dump_t; + +typedef VL_API_PACKED(struct _vl_api_dhcp_server { + u32 server_vrf_id; + u8 dhcp_server[16]; +}) vl_api_dhcp_server_t; + +typedef VL_API_PACKED(struct _vl_api_dhcp_proxy_details { + u16 _vl_msg_id; + u32 context; + u32 rx_vrf_id; + u32 vss_oui; + u32 vss_fib_id; + u8 is_ipv6; + u8 dhcp_src_address[16]; + u8 count; + vl_api_dhcp_server_t servers[0]; +}) vl_api_dhcp_proxy_details_t; + +#endif /* vl_typedefs */ + +/****** Discriminated Union Definitions *****/ + +#ifdef vl_union_id + + +#endif /* vl_union_id */ + +/****** Print functions *****/ + +#ifdef vl_printfun + +#ifdef LP64 +#define _uword_fmt "%lld" +#define _uword_cast (long long) +#else +#define _uword_fmt "%ld" +#define _uword_cast long +#endif + +static inline void *vl_api_dhcp_proxy_config_t_print (vl_api_dhcp_proxy_config_t *a,void *handle) +{ + vl_print(handle, "vl_api_dhcp_proxy_config_t:\n"); + vl_print(handle, "_vl_msg_id: %u\n", (unsigned) a->_vl_msg_id); + vl_print(handle, "client_index: %u\n", (unsigned) a->client_index); + vl_print(handle, "context: %u\n", (unsigned) a->context); + vl_print(handle, "rx_vrf_id: %u\n", (unsigned) a->rx_vrf_id); + vl_print(handle, "server_vrf_id: %u\n", (unsigned) a->server_vrf_id); + vl_print(handle, "is_ipv6: %u\n", (unsigned) a->is_ipv6); + vl_print(handle, "is_add: %u\n", (unsigned) a->is_add); + { + int _i; + for (_i = 0; _i < 16; _i++) { + vl_print(handle, "dhcp_server[%d]: %u\n", _i, a->dhcp_server[_i]); + } + } + { + int _i; + for (_i = 0; _i < 16; _i++) { + vl_print(handle, "dhcp_src_address[%d]: %u\n", _i, a->dhcp_src_address[_i]); + } + } + return handle; +} + +static inline void *vl_api_dhcp_proxy_config_reply_t_print (vl_api_dhcp_proxy_config_reply_t *a,void *handle) +{ + vl_print(handle, "vl_api_dhcp_proxy_config_reply_t:\n"); + vl_print(handle, "_vl_msg_id: %u\n", (unsigned) a->_vl_msg_id); + vl_print(handle, "context: %u\n", (unsigned) a->context); + vl_print(handle, "retval: %ld\n", (long) a->retval); + return handle; +} + +static inline void *vl_api_dhcp_proxy_set_vss_t_print (vl_api_dhcp_proxy_set_vss_t *a,void *handle) +{ + vl_print(handle, "vl_api_dhcp_proxy_set_vss_t:\n"); + vl_print(handle, "_vl_msg_id: %u\n", (unsigned) a->_vl_msg_id); + vl_print(handle, "client_index: %u\n", (unsigned) a->client_index); + vl_print(handle, "context: %u\n", (unsigned) a->context); + vl_print(handle, "tbl_id: %u\n", (unsigned) a->tbl_id); + vl_print(handle, "oui: %u\n", (unsigned) a->oui); + vl_print(handle, "fib_id: %u\n", (unsigned) a->fib_id); + vl_print(handle, "is_ipv6: %u\n", (unsigned) a->is_ipv6); + vl_print(handle, "is_add: %u\n", (unsigned) a->is_add); + return handle; +} + +static inline void *vl_api_dhcp_proxy_set_vss_reply_t_print (vl_api_dhcp_proxy_set_vss_reply_t *a,void *handle) +{ + vl_print(handle, "vl_api_dhcp_proxy_set_vss_reply_t:\n"); + vl_print(handle, "_vl_msg_id: %u\n", (unsigned) a->_vl_msg_id); + vl_print(handle, "context: %u\n", (unsigned) a->context); + vl_print(handle, "retval: %ld\n", (long) a->retval); + return handle; +} + +static inline void *vl_api_dhcp_client_config_t_print (vl_api_dhcp_client_config_t *a,void *handle) +{ + vl_print(handle, "vl_api_dhcp_client_config_t:\n"); + vl_print(handle, "_vl_msg_id: %u\n", (unsigned) a->_vl_msg_id); + vl_print(handle, "client_index: %u\n", (unsigned) a->client_index); + vl_print(handle, "context: %u\n", (unsigned) a->context); + vl_print(handle, "sw_if_index: %u\n", (unsigned) a->sw_if_index); + { + int _i; + for (_i = 0; _i < 64; _i++) { + vl_print(handle, "hostname[%d]: %u\n", _i, a->hostname[_i]); + } + } + vl_print(handle, "is_add: %u\n", (unsigned) a->is_add); + vl_print(handle, "want_dhcp_event: %u\n", (unsigned) a->want_dhcp_event); + vl_print(handle, "pid: %u\n", (unsigned) a->pid); + return handle; +} + +static inline void *vl_api_dhcp_client_config_reply_t_print (vl_api_dhcp_client_config_reply_t *a,void *handle) +{ + vl_print(handle, "vl_api_dhcp_client_config_reply_t:\n"); + vl_print(handle, "_vl_msg_id: %u\n", (unsigned) a->_vl_msg_id); + vl_print(handle, "context: %u\n", (unsigned) a->context); + vl_print(handle, "retval: %ld\n", (long) a->retval); + return handle; +} + +static inline void *vl_api_dhcp_compl_event_t_print (vl_api_dhcp_compl_event_t *a,void *handle) +{ + vl_print(handle, "vl_api_dhcp_compl_event_t:\n"); + vl_print(handle, "_vl_msg_id: %u\n", (unsigned) a->_vl_msg_id); + vl_print(handle, "client_index: %u\n", (unsigned) a->client_index); + vl_print(handle, "pid: %u\n", (unsigned) a->pid); + { + int _i; + for (_i = 0; _i < 64; _i++) { + vl_print(handle, "hostname[%d]: %u\n", _i, a->hostname[_i]); + } + } + vl_print(handle, "is_ipv6: %u\n", (unsigned) a->is_ipv6); + { + int _i; + for (_i = 0; _i < 16; _i++) { + vl_print(handle, "host_address[%d]: %u\n", _i, a->host_address[_i]); + } + } + { + int _i; + for (_i = 0; _i < 16; _i++) { + vl_print(handle, "router_address[%d]: %u\n", _i, a->router_address[_i]); + } + } + { + int _i; + for (_i = 0; _i < 6; _i++) { + vl_print(handle, "host_mac[%d]: %u\n", _i, a->host_mac[_i]); + } + } + return handle; +} + +static inline void *vl_api_dhcp_proxy_dump_t_print (vl_api_dhcp_proxy_dump_t *a,void *handle) +{ + vl_print(handle, "vl_api_dhcp_proxy_dump_t:\n"); + vl_print(handle, "_vl_msg_id: %u\n", (unsigned) a->_vl_msg_id); + vl_print(handle, "client_index: %u\n", (unsigned) a->client_index); + vl_print(handle, "context: %u\n", (unsigned) a->context); + vl_print(handle, "is_ip6: %u\n", (unsigned) a->is_ip6); + return handle; +} + +/***** manual: vl_api_dhcp_server_t_print *****/ + +/***** manual: vl_api_dhcp_proxy_details_t_print *****/ + +#endif /* vl_printfun */ + + +/****** Endian swap functions *****/ + +#ifdef vl_endianfun + +#undef clib_net_to_host_uword +#ifdef LP64 +#define clib_net_to_host_uword clib_net_to_host_u64 +#else +#define clib_net_to_host_uword clib_net_to_host_u32 +#endif + +static inline void vl_api_dhcp_proxy_config_t_endian (vl_api_dhcp_proxy_config_t *a) +{ + a->_vl_msg_id = clib_net_to_host_u16(a->_vl_msg_id); + a->client_index = clib_net_to_host_u32(a->client_index); + a->context = clib_net_to_host_u32(a->context); + a->rx_vrf_id = clib_net_to_host_u32(a->rx_vrf_id); + a->server_vrf_id = clib_net_to_host_u32(a->server_vrf_id); + /* a->is_ipv6 = a->is_ipv6 (no-op) */ + /* a->is_add = a->is_add (no-op) */ + /* a->dhcp_server[0..15] = a->dhcp_server[0..15] (no-op) */ + /* a->dhcp_src_address[0..15] = a->dhcp_src_address[0..15] (no-op) */ +} + +static inline void vl_api_dhcp_proxy_config_reply_t_endian (vl_api_dhcp_proxy_config_reply_t *a) +{ + a->_vl_msg_id = clib_net_to_host_u16(a->_vl_msg_id); + a->context = clib_net_to_host_u32(a->context); + a->retval = clib_net_to_host_u32(a->retval); +} + +static inline void vl_api_dhcp_proxy_set_vss_t_endian (vl_api_dhcp_proxy_set_vss_t *a) +{ + a->_vl_msg_id = clib_net_to_host_u16(a->_vl_msg_id); + a->client_index = clib_net_to_host_u32(a->client_index); + a->context = clib_net_to_host_u32(a->context); + a->tbl_id = clib_net_to_host_u32(a->tbl_id); + a->oui = clib_net_to_host_u32(a->oui); + a->fib_id = clib_net_to_host_u32(a->fib_id); + /* a->is_ipv6 = a->is_ipv6 (no-op) */ + /* a->is_add = a->is_add (no-op) */ +} + +static inline void vl_api_dhcp_proxy_set_vss_reply_t_endian (vl_api_dhcp_proxy_set_vss_reply_t *a) +{ + a->_vl_msg_id = clib_net_to_host_u16(a->_vl_msg_id); + a->context = clib_net_to_host_u32(a->context); + a->retval = clib_net_to_host_u32(a->retval); +} + +static inline void vl_api_dhcp_client_config_t_endian (vl_api_dhcp_client_config_t *a) +{ + a->_vl_msg_id = clib_net_to_host_u16(a->_vl_msg_id); + a->client_index = clib_net_to_host_u32(a->client_index); + a->context = clib_net_to_host_u32(a->context); + a->sw_if_index = clib_net_to_host_u32(a->sw_if_index); + /* a->hostname[0..63] = a->hostname[0..63] (no-op) */ + /* a->is_add = a->is_add (no-op) */ + /* a->want_dhcp_event = a->want_dhcp_event (no-op) */ + a->pid = clib_net_to_host_u32(a->pid); +} + +static inline void vl_api_dhcp_client_config_reply_t_endian (vl_api_dhcp_client_config_reply_t *a) +{ + a->_vl_msg_id = clib_net_to_host_u16(a->_vl_msg_id); + a->context = clib_net_to_host_u32(a->context); + a->retval = clib_net_to_host_u32(a->retval); +} + +static inline void vl_api_dhcp_compl_event_t_endian (vl_api_dhcp_compl_event_t *a) +{ + a->_vl_msg_id = clib_net_to_host_u16(a->_vl_msg_id); + a->client_index = clib_net_to_host_u32(a->client_index); + a->pid = clib_net_to_host_u32(a->pid); + /* a->hostname[0..63] = a->hostname[0..63] (no-op) */ + /* a->is_ipv6 = a->is_ipv6 (no-op) */ + /* a->host_address[0..15] = a->host_address[0..15] (no-op) */ + /* a->router_address[0..15] = a->router_address[0..15] (no-op) */ + /* a->host_mac[0..5] = a->host_mac[0..5] (no-op) */ +} + +static inline void vl_api_dhcp_proxy_dump_t_endian (vl_api_dhcp_proxy_dump_t *a) +{ + a->_vl_msg_id = clib_net_to_host_u16(a->_vl_msg_id); + a->client_index = clib_net_to_host_u32(a->client_index); + a->context = clib_net_to_host_u32(a->context); + /* a->is_ip6 = a->is_ip6 (no-op) */ +} + +/***** manual: vl_api_dhcp_server_t_endian *****/ + +/***** manual: vl_api_dhcp_proxy_details_t_endian *****/ + +#endif /* vl_endianfun */ + + +#ifdef vl_api_version +vl_api_version(dhcp.api, 0x214119c5) + +#endif + diff --git a/src/configure.ac b/src/configure.ac index fb2ead6..ef5537d 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -152,6 +152,7 @@ PLUGIN_ENABLED(ioam) PLUGIN_ENABLED(ixge) PLUGIN_ENABLED(lb) PLUGIN_ENABLED(memif) +PLUGIN_ENABLED(vbng) PLUGIN_ENABLED(sixrd) PLUGIN_ENABLED(snat) diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index 623892e..d6f607f 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -61,6 +61,10 @@ if ENABLE_MEMIF_PLUGIN include memif.am endif +if ENABLE_VBNG_PLUGIN +include vbng.am +endif + if ENABLE_SIXRD_PLUGIN include sixrd.am endif diff --git a/src/plugins/vbng.am b/src/plugins/vbng.am new file mode 100644 index 0000000..99398f4 --- /dev/null +++ b/src/plugins/vbng.am @@ -0,0 +1,32 @@ +# Copyright (c) 2017 Intel and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +vppplugins_LTLIBRARIES += vbng_plugin.la + +vbng_plugin_la_LDFLAGS = $(AM_LDFLAGS) -lfreeradiusclient + +vbng_plugin_la_SOURCES = vbng/vbng_dhcp4_node.c \ + vbng/vbng_dhcp4.c \ + vbng/vbng_api.c \ + vbng/vbng_aaa.c + +BUILT_SOURCES += vbng/vbng.api.h \ + vbng/vbng.api.json + +API_FILES += vbng/vbng.api + +nobase_apiinclude_HEADERS += vbng/vbng_all_api_h.h \ + vbng/vbng_msg_enum.h \ + vbng/vbng.api.h + +# vi:syntax=automake diff --git a/src/plugins/vbng/etc/dictionary b/src/plugins/vbng/etc/dictionary new file mode 100644 index 0000000..45f4189 --- /dev/null +++ b/src/plugins/vbng/etc/dictionary @@ -0,0 +1,274 @@ +# +# Updated 97/06/13 to livingston-radius-2.01 miquels@cistron.nl +# +# This file contains dictionary translations for parsing +# requests and generating responses. All transactions are +# composed of Attribute/Value Pairs. The value of each attribute +# is specified as one of 4 data types. Valid data types are: +# +# string - 0-253 octets +# ipaddr - 4 octets in network byte order +# integer - 32 bit value in big endian order (high byte first) +# date - 32 bit value in big endian order - seconds since +# 00:00:00 GMT, Jan. 1, 1970 +# +# Enumerated values are stored in the user file with dictionary +# VALUE translations for easy administration. +# +# Example: +# +# ATTRIBUTE VALUE +# --------------- ----- +# Framed-Protocol = PPP +# 7 = 1 (integer encoding) +# + +# +# Following are the proper new names. Use these. +# +ATTRIBUTE User-Name 1 string +ATTRIBUTE Password 2 string +ATTRIBUTE CHAP-Password 3 string +ATTRIBUTE NAS-IP-Address 4 ipaddr +ATTRIBUTE NAS-Port-Id 5 integer +ATTRIBUTE Service-Type 6 integer +ATTRIBUTE Framed-Protocol 7 integer +ATTRIBUTE Framed-IP-Address 8 ipaddr +ATTRIBUTE Framed-IP-Netmask 9 ipaddr +ATTRIBUTE Framed-Routing 10 integer +ATTRIBUTE Filter-Id 11 string +ATTRIBUTE Framed-MTU 12 integer +ATTRIBUTE Framed-Compression 13 integer +ATTRIBUTE Login-IP-Host 14 ipaddr +ATTRIBUTE Login-Service 15 integer +ATTRIBUTE Login-TCP-Port 16 integer +ATTRIBUTE Reply-Message 18 string +ATTRIBUTE Callback-Number 19 string +ATTRIBUTE Callback-Id 20 string +ATTRIBUTE Framed-Route 22 string +ATTRIBUTE Framed-IPX-Network 23 ipaddr +ATTRIBUTE State 24 string +ATTRIBUTE Class 25 string +ATTRIBUTE Vendor-Specific 26 string +ATTRIBUTE Session-Timeout 27 integer +ATTRIBUTE Idle-Timeout 28 integer +ATTRIBUTE Termination-Action 29 integer +ATTRIBUTE Called-Station-Id 30 string +ATTRIBUTE Calling-Station-Id 31 string +ATTRIBUTE NAS-Identifier 32 string +ATTRIBUTE Proxy-State 33 string +ATTRIBUTE Login-LAT-Service 34 string +ATTRIBUTE Login-LAT-Node 35 string +ATTRIBUTE Login-LAT-Group 36 string +ATTRIBUTE Framed-AppleTalk-Link 37 integer +ATTRIBUTE Framed-AppleTalk-Network 38 integer +ATTRIBUTE Framed-AppleTalk-Zone 39 string +ATTRIBUTE Acct-Status-Type 40 integer +ATTRIBUTE Acct-Delay-Time 41 integer +ATTRIBUTE Acct-Input-Octets 42 integer +ATTRIBUTE Acct-Output-Octets 43 integer +ATTRIBUTE Acct-Session-Id 44 string +ATTRIBUTE Acct-Authentic 45 integer +ATTRIBUTE Acct-Session-Time 46 integer +ATTRIBUTE Acct-Input-Packets 47 integer +ATTRIBUTE Acct-Output-Packets 48 integer +ATTRIBUTE Acct-Terminate-Cause 49 integer +ATTRIBUTE Acct-Multi-Session-Id 50 string +ATTRIBUTE Acct-Link-Count 51 integer +ATTRIBUTE Acct-Input-Gigawords 52 integer +ATTRIBUTE Acct-Output-Gigawords 53 integer +ATTRIBUTE Event-Timestamp 55 integer +ATTRIBUTE CHAP-Challenge 60 string +ATTRIBUTE NAS-Port-Type 61 integer +ATTRIBUTE Port-Limit 62 integer +ATTRIBUTE Login-LAT-Port 63 integer +ATTRIBUTE Connect-Info 77 string + +# +# RFC3162 IPv6 attributes +# +ATTRIBUTE NAS-IPv6-Address 95 string +ATTRIBUTE Framed-Interface-Id 96 string +ATTRIBUTE Framed-IPv6-Prefix 97 ipv6prefix +ATTRIBUTE Login-IPv6-Host 98 string +ATTRIBUTE Framed-IPv6-Route 99 string +ATTRIBUTE Framed-IPv6-Pool 100 string + +# +# RFC6911 IPv6 attributes +# +ATTRIBUTE Framed-IPv6-Address 168 ipv6addr +ATTRIBUTE DNS-Server-IPv6-Address 169 ipv6addr +ATTRIBUTE Route-IPv6-Information 170 ipv6prefix + +# +# Experimental Non Protocol Attributes used by Cistron-Radiusd +# +ATTRIBUTE Huntgroup-Name 221 string +ATTRIBUTE User-Category 1029 string +ATTRIBUTE Group-Name 1030 string +ATTRIBUTE Simultaneous-Use 1034 integer +ATTRIBUTE Strip-User-Name 1035 integer +ATTRIBUTE Fall-Through 1036 integer +ATTRIBUTE Add-Port-To-IP-Address 1037 integer +ATTRIBUTE Exec-Program 1038 string +ATTRIBUTE Exec-Program-Wait 1039 string +ATTRIBUTE Hint 1040 string + +# +# Non-Protocol Attributes +# These attributes are used internally by the server +# +ATTRIBUTE Expiration 21 date +ATTRIBUTE Auth-Type 1000 integer +ATTRIBUTE Menu 1001 string +ATTRIBUTE Termination-Menu 1002 string +ATTRIBUTE Prefix 1003 string +ATTRIBUTE Suffix 1004 string +ATTRIBUTE Group 1005 string +ATTRIBUTE Crypt-Password 1006 string +ATTRIBUTE Connect-Rate 1007 integer + +# +# Integer Translations +# + +# User Types + +VALUE Service-Type Login-User 1 +VALUE Service-Type Framed-User 2 +VALUE Service-Type Callback-Login-User 3 +VALUE Service-Type Callback-Framed-User 4 +VALUE Service-Type Outbound-User 5 +VALUE Service-Type Administrative-User 6 +VALUE Service-Type NAS-Prompt-User 7 +VALUE Service-Type Authenticate-Only 8 +VALUE Service-Type Callback-NAS-Prompt 9 +VALUE Service-Type Call-Check 10 +VALUE Service-Type Callback-Administrative 11 + +# Framed Protocols + +VALUE Framed-Protocol PPP 1 +VALUE Framed-Protocol SLIP 2 +VALUE Framed-Protocol ARAP 3 +VALUE Framed-Protocol GANDALF-SLMLP 4 +VALUE Framed-Protocol XYLOGICS-IPX-SLIP 5 +VALUE Framed-Protocol X75 6 + +# Framed Routing Values + +VALUE Framed-Routing None 0 +VALUE Framed-Routing Broadcast 1 +VALUE Framed-Routing Listen 2 +VALUE Framed-Routing Broadcast-Listen 3 + +# Framed Compression Types + +VALUE Framed-Compression None 0 +VALUE Framed-Compression Van-Jacobson-TCP-IP 1 +VALUE Framed-Compression IPX-Header 2 +VALUE Framed-Compression Stac-LZS 3 + +# Login Services + +VALUE Login-Service Telnet 0 +VALUE Login-Service Rlogin 1 +VALUE Login-Service TCP-Clear 2 +VALUE Login-Service PortMaster 3 +VALUE Login-Service LAT 4 +VALUE Login-Service X.25-PAD 5 +VALUE Login-Service X.25-T3POS 6 +VALUE Login-Service TCP-Clear-Quiet 8 + +# Status Types + +VALUE Acct-Status-Type Start 1 +VALUE Acct-Status-Type Stop 2 +VALUE Acct-Status-Type Alive 3 +VALUE Acct-Status-Type Accounting-On 7 +VALUE Acct-Status-Type Accounting-Off 8 + +# Authentication Types + +VALUE Acct-Authentic RADIUS 1 +VALUE Acct-Authentic Local 2 +VALUE Acct-Authentic Remote 3 + +# Termination Options + +VALUE Termination-Action Default 0 +VALUE Termination-Action RADIUS-Request 1 + +# NAS Port Types, available in 3.3.1 and later + +VALUE NAS-Port-Type Async 0 +VALUE NAS-Port-Type Sync 1 +VALUE NAS-Port-Type ISDN 2 +VALUE NAS-Port-Type ISDN-V120 3 +VALUE NAS-Port-Type ISDN-V110 4 +VALUE NAS-Port-Type Virtual 5 +VALUE NAS-Port-Type PIAFS 6 +VALUE NAS-Port-Type HDLC-Clear-Channel 7 +VALUE NAS-Port-Type X.25 8 +VALUE NAS-Port-Type X.75 9 +VALUE NAS-Port-Type G.3-Fax 10 +VALUE NAS-Port-Type SDSL 11 +VALUE NAS-Port-Type ADSL-CAP 12 +VALUE NAS-Port-Type ADSL-DMT 13 +VALUE NAS-Port-Type IDSL 14 +VALUE NAS-Port-Type Ethernet 15 + +# Acct Terminate Causes, available in 3.3.2 and later + +VALUE Acct-Terminate-Cause User-Request 1 +VALUE Acct-Terminate-Cause Lost-Carrier 2 +VALUE Acct-Terminate-Cause Lost-Service 3 +VALUE Acct-Terminate-Cause Idle-Timeout 4 +VALUE Acct-Terminate-Cause Session-Timeout 5 +VALUE Acct-Terminate-Cause Admin-Reset 6 +VALUE Acct-Terminate-Cause Admin-Reboot 7 +VALUE Acct-Terminate-Cause Port-Error 8 +VALUE Acct-Terminate-Cause NAS-Error 9 +VALUE Acct-Terminate-Cause NAS-Request 10 +VALUE Acct-Terminate-Cause NAS-Reboot 11 +VALUE Acct-Terminate-Cause Port-Unneeded 12 +VALUE Acct-Terminate-Cause Port-Preempted 13 +VALUE Acct-Terminate-Cause Port-Suspended 14 +VALUE Acct-Terminate-Cause Service-Unavailable 15 +VALUE Acct-Terminate-Cause Callback 16 +VALUE Acct-Terminate-Cause User-Error 17 +VALUE Acct-Terminate-Cause Host-Request 18 + +# +# Non-Protocol Integer Translations +# + +VALUE Auth-Type Local 0 +VALUE Auth-Type System 1 +VALUE Auth-Type SecurID 2 +VALUE Auth-Type Crypt-Local 3 +VALUE Auth-Type Reject 4 + +# +# Cistron extensions +# +VALUE Auth-Type Pam 253 +VALUE Auth-Type Accept 254 + +# +# Experimental Non-Protocol Integer Translations for Cistron-Radiusd +# +VALUE Fall-Through No 0 +VALUE Fall-Through Yes 1 +VALUE Add-Port-To-IP-Address No 0 +VALUE Add-Port-To-IP-Address Yes 1 + +# +# Configuration Values +# uncomment these two lines to turn account expiration on +# + +#VALUE Server-Config Password-Expiration 30 +#VALUE Server-Config Password-Warning 5 + diff --git a/src/plugins/vbng/etc/dictionary.ascend b/src/plugins/vbng/etc/dictionary.ascend new file mode 100644 index 0000000..a02c207 --- /dev/null +++ b/src/plugins/vbng/etc/dictionary.ascend @@ -0,0 +1,297 @@ +# +# Ascend dictionary. +# +# Enable by putting the line "$INCLUDE dictionary.ascend" into +# the main dictionary file. +# +# Version: 1.00 21-Jul-1997 Jens Glaser +# + + +# +# Ascend specific extensions +# Used by ASCEND MAX/Pipeline products +# +ATTRIBUTE Ascend-FCP-Parameter 119 string +ATTRIBUTE Ascend-Modem-PortNo 120 integer +ATTRIBUTE Ascend-Modem-SlotNo 121 integer +ATTRIBUTE Ascend-Modem-ShelfNo 122 integer +ATTRIBUTE Ascend-Call-Attempt-Limit 123 integer +ATTRIBUTE Ascend-Call-Block-Duration 124 integer +ATTRIBUTE Ascend-Maximum-Call-Duration 125 integer +ATTRIBUTE Ascend-Temporary-Rtes 126 integer +ATTRIBUTE Tunneling-Protocol 127 integer +ATTRIBUTE Ascend-Shared-Profile-Enable 128 integer +ATTRIBUTE Ascend-Primary-Home-Agent 129 string +ATTRIBUTE Ascend-Secondary-Home-Agent 130 string +ATTRIBUTE Ascend-Dialout-Allowed 131 integer +ATTRIBUTE Ascend-Client-Gateway 132 ipaddr +ATTRIBUTE Ascend-BACP-Enable 133 integer +ATTRIBUTE Ascend-DHCP-Maximum-Leases 134 integer +ATTRIBUTE Ascend-Client-Primary-DNS 135 ipaddr +ATTRIBUTE Ascend-Client-Secondary-DNS 136 ipaddr +ATTRIBUTE Ascend-Client-Assign-DNS 137 integer +ATTRIBUTE Ascend-User-Acct-Type 138 integer +ATTRIBUTE Ascend-User-Acct-Host 139 ipaddr +ATTRIBUTE Ascend-User-Acct-Port 140 integer +ATTRIBUTE Ascend-User-Acct-Key 141 string +ATTRIBUTE Ascend-User-Acct-Base 142 integer +ATTRIBUTE Ascend-User-Acct-Time 143 integer +ATTRIBUTE Ascend-Assign-IP-Client 144 ipaddr +ATTRIBUTE Ascend-Assign-IP-Server 145 ipaddr +ATTRIBUTE Ascend-Assign-IP-Global-Pool 146 string +ATTRIBUTE Ascend-DHCP-Reply 147 integer +ATTRIBUTE Ascend-DHCP-Pool-Number 148 integer +ATTRIBUTE Ascend-Expect-Callback 149 integer +ATTRIBUTE Ascend-Event-Type 150 integer +ATTRIBUTE Ascend-Session-Svr-Key 151 string +ATTRIBUTE Ascend-Multicast-Rate-Limit 152 integer +ATTRIBUTE Ascend-IF-Netmask 153 ipaddr +ATTRIBUTE Ascend-Remote-Addr 154 ipaddr +ATTRIBUTE Ascend-Multicast-Client 155 integer +ATTRIBUTE Ascend-FR-Circuit-Name 156 string +ATTRIBUTE Ascend-FR-LinkUp 157 integer +ATTRIBUTE Ascend-FR-Nailed-Grp 158 integer +ATTRIBUTE Ascend-FR-Type 159 integer +ATTRIBUTE Ascend-FR-Link-Mgt 160 integer +ATTRIBUTE Ascend-FR-N391 161 integer +ATTRIBUTE Ascend-FR-DCE-N392 162 integer +ATTRIBUTE Ascend-FR-DTE-N392 163 integer +ATTRIBUTE Ascend-FR-DCE-N393 164 integer +ATTRIBUTE Ascend-FR-DTE-N393 165 integer +ATTRIBUTE Ascend-FR-T391 166 integer +ATTRIBUTE Ascend-FR-T392 167 integer +ATTRIBUTE Ascend-Bridge-Address 168 string +ATTRIBUTE Ascend-TS-Idle-Limit 169 integer +ATTRIBUTE Ascend-TS-Idle-Mode 170 integer +ATTRIBUTE Ascend-DBA-Monitor 171 integer +ATTRIBUTE Ascend-Base-Channel-Count 172 integer +ATTRIBUTE Ascend-Minimum-Channels 173 integer +ATTRIBUTE Ascend-IPX-Route 174 string +ATTRIBUTE Ascend-FT1-Caller 175 integer +ATTRIBUTE Ascend-Backup 176 string +ATTRIBUTE Ascend-Call-Type 177 integer +ATTRIBUTE Ascend-Group 178 string +ATTRIBUTE Ascend-FR-DLCI 179 integer +ATTRIBUTE Ascend-FR-Profile-Name 180 string +ATTRIBUTE Ascend-Ara-PW 181 string +ATTRIBUTE Ascend-IPX-Node-Addr 182 string +ATTRIBUTE Ascend-Home-Agent-IP-Addr 183 ipaddr +ATTRIBUTE Ascend-Home-Agent-Password 184 string +ATTRIBUTE Ascend-Home-Network-Name 185 string +ATTRIBUTE Ascend-Home-Agent-UDP-Port 186 integer +ATTRIBUTE Ascend-Multilink-ID 187 integer +ATTRIBUTE Ascend-Num-In-Multilink 188 integer +ATTRIBUTE Ascend-First-Dest 189 ipaddr +ATTRIBUTE Ascend-Pre-Input-Octets 190 integer +ATTRIBUTE Ascend-Pre-Output-Octets 191 integer +ATTRIBUTE Ascend-Pre-Input-Packets 192 integer +ATTRIBUTE Ascend-Pre-Output-Packets 193 integer +ATTRIBUTE Ascend-Maximum-Time 194 integer +ATTRIBUTE Ascend-Disconnect-Cause 195 integer +ATTRIBUTE Ascend-Connect-Progress 196 integer +ATTRIBUTE Ascend-Data-Rate 197 integer +ATTRIBUTE Ascend-PreSession-Time 198 integer +ATTRIBUTE Ascend-Token-Idle 199 integer +ATTRIBUTE Ascend-Token-Immediate 200 integer +ATTRIBUTE Ascend-Require-Auth 201 integer +ATTRIBUTE Ascend-Number-Sessions 202 string +ATTRIBUTE Ascend-Authen-Alias 203 string +ATTRIBUTE Ascend-Token-Expiry 204 integer +ATTRIBUTE Ascend-Menu-Selector 205 string +ATTRIBUTE Ascend-Menu-Item 206 string +ATTRIBUTE Ascend-PW-Warntime 207 integer +ATTRIBUTE Ascend-PW-Lifetime 208 integer +ATTRIBUTE Ascend-IP-Direct 209 ipaddr +ATTRIBUTE Ascend-PPP-VJ-Slot-Comp 210 integer +ATTRIBUTE Ascend-PPP-VJ-1172 211 integer +ATTRIBUTE Ascend-PPP-Async-Map 212 integer +ATTRIBUTE Ascend-Third-Prompt 213 string +ATTRIBUTE Ascend-Send-Secret 214 string +ATTRIBUTE Ascend-Receive-Secret 215 string +ATTRIBUTE Ascend-IPX-Peer-Mode 216 integer +ATTRIBUTE Ascend-IP-Pool-Definition 217 string +ATTRIBUTE Ascend-Assign-IP-Pool 218 integer +ATTRIBUTE Ascend-FR-Direct 219 integer +ATTRIBUTE Ascend-FR-Direct-Profile 220 string +ATTRIBUTE Ascend-FR-Direct-DLCI 221 integer +ATTRIBUTE Ascend-Handle-IPX 222 integer +ATTRIBUTE Ascend-Netware-timeout 223 integer +ATTRIBUTE Ascend-IPX-Alias 224 integer +ATTRIBUTE Ascend-Metric 225 integer +ATTRIBUTE Ascend-PRI-Number-Type 226 integer +ATTRIBUTE Ascend-Dial-Number 227 string +ATTRIBUTE Ascend-Route-IP 228 integer +ATTRIBUTE Ascend-Route-IPX 229 integer +ATTRIBUTE Ascend-Bridge 230 integer +ATTRIBUTE Ascend-Send-Auth 231 integer +ATTRIBUTE Ascend-Send-Passwd 232 string +ATTRIBUTE Ascend-Link-Compression 233 integer +ATTRIBUTE Ascend-Target-Util 234 integer +ATTRIBUTE Ascend-Maximum-Channels 235 integer +ATTRIBUTE Ascend-Inc-Channel-Count 236 integer +ATTRIBUTE Ascend-Dec-Channel-Count 237 integer +ATTRIBUTE Ascend-Seconds-Of-History 238 integer +ATTRIBUTE Ascend-History-Weigh-Type 239 integer +ATTRIBUTE Ascend-Add-Seconds 240 integer +ATTRIBUTE Ascend-Remove-Seconds 241 integer +ATTRIBUTE Ascend-Idle-Limit 244 integer +ATTRIBUTE Ascend-Preempt-Limit 245 integer +ATTRIBUTE Ascend-Callback 246 integer +ATTRIBUTE Ascend-Data-Svc 247 integer +ATTRIBUTE Ascend-Force-56 248 integer +ATTRIBUTE Ascend-Billing-Number 249 string +ATTRIBUTE Ascend-Call-By-Call 250 integer +ATTRIBUTE Ascend-Transit-Number 251 string +ATTRIBUTE Ascend-Host-Info 252 string +ATTRIBUTE Ascend-PPP-Address 253 ipaddr +ATTRIBUTE Ascend-MPP-Idle-Percent 254 integer +ATTRIBUTE Ascend-Xmit-Rate 255 integer + + + +# Ascend protocols +VALUE Service-Type Dialout-Framed-User 5 +VALUE Framed-Protocol ARA 255 +VALUE Framed-Protocol MPP 256 +VALUE Framed-Protocol EURAW 257 +VALUE Framed-Protocol EUUI 258 +VALUE Framed-Protocol X25 259 +VALUE Framed-Protocol COMB 260 +VALUE Framed-Protocol FR 261 +VALUE Framed-Protocol MP 262 +VALUE Framed-Protocol FR-CIR 263 + + +# +# Ascend specific extensions +# Used by ASCEND MAX/Pipeline products (see above) +# + +VALUE Ascend-FR-Direct FR-Direct-No 0 +VALUE Ascend-FR-Direct FR-Direct-Yes 1 +VALUE Ascend-Handle-IPX Handle-IPX-None 0 +VALUE Ascend-Handle-IPX Handle-IPX-Client 1 +VALUE Ascend-Handle-IPX Handle-IPX-Server 2 +VALUE Ascend-IPX-Peer-Mode IPX-Peer-Router 0 +VALUE Ascend-IPX-Peer-Mode IPX-Peer-Dialin 1 +VALUE Ascend-Call-Type Nailed 1 +VALUE Ascend-Call-Type Nailed/Mpp 2 +VALUE Ascend-Call-Type Perm/Switched 3 +VALUE Ascend-FT1-Caller FT1-No 0 +VALUE Ascend-FT1-Caller FT1-Yes 1 +VALUE Ascend-PRI-Number-Type Unknown-Number 0 +VALUE Ascend-PRI-Number-Type Intl-Number 1 +VALUE Ascend-PRI-Number-Type National-Number 2 +VALUE Ascend-PRI-Number-Type Local-Number 4 +VALUE Ascend-PRI-Number-Type Abbrev-Number 5 +VALUE Ascend-Route-IPX Route-IPX-No 0 +VALUE Ascend-Route-IPX Route-IPX-Yes 1 +VALUE Ascend-Bridge Bridge-No 0 +VALUE Ascend-Bridge Bridge-Yes 1 +VALUE Ascend-TS-Idle-Mode TS-Idle-None 0 +VALUE Ascend-TS-Idle-Mode TS-Idle-Input 1 +VALUE Ascend-TS-Idle-Mode TS-Idle-Input-Output 2 +VALUE Ascend-Send-Auth Send-Auth-None 0 +VALUE Ascend-Send-Auth Send-Auth-PAP 1 +VALUE Ascend-Send-Auth Send-Auth-CHAP 2 +VALUE Ascend-Send-Auth Send-Auth-MS-CHAP 3 +VALUE Ascend-Link-Compression Link-Comp-None 0 +VALUE Ascend-Link-Compression Link-Comp-Stac 1 +VALUE Ascend-Link-Compression Link-Comp-Stac-Draft-9 2 +VALUE Ascend-Link-Compression Link-Comp-MS-Stac 3 +VALUE Ascend-History-Weigh-Type History-Constant 0 +VALUE Ascend-History-Weigh-Type History-Linear 1 +VALUE Ascend-History-Weigh-Type History-Quadratic 2 +VALUE Ascend-Callback Callback-No 0 +VALUE Ascend-Callback Callback-Yes 1 +VALUE Ascend-Expect-Callback Expect-Callback-No 0 +VALUE Ascend-Expect-Callback Expect-Callback-Yes 1 +VALUE Ascend-Data-Svc Switched-Voice-Bearer 0 +VALUE Ascend-Data-Svc Switched-56KR 1 +VALUE Ascend-Data-Svc Switched-64K 2 +VALUE Ascend-Data-Svc Switched-64KR 3 +VALUE Ascend-Data-Svc Switched-56K 4 +VALUE Ascend-Data-Svc Switched-384KR 5 +VALUE Ascend-Data-Svc Switched-384K 6 +VALUE Ascend-Data-Svc Switched-1536K 7 +VALUE Ascend-Data-Svc Switched-1536KR 8 +VALUE Ascend-Data-Svc Switched-128K 9 +VALUE Ascend-Data-Svc Switched-192K 10 +VALUE Ascend-Data-Svc Switched-256K 11 +VALUE Ascend-Data-Svc Switched-320K 12 +VALUE Ascend-Data-Svc Switched-384K-MR 13 +VALUE Ascend-Data-Svc Switched-448K 14 +VALUE Ascend-Data-Svc Switched-512K 15 +VALUE Ascend-Data-Svc Switched-576K 16 +VALUE Ascend-Data-Svc Switched-640K 17 +VALUE Ascend-Data-Svc Switched-704K 18 +VALUE Ascend-Data-Svc Switched-768K 19 +VALUE Ascend-Data-Svc Switched-832K 20 +VALUE Ascend-Data-Svc Switched-896K 21 +VALUE Ascend-Data-Svc Switched-960K 22 +VALUE Ascend-Data-Svc Switched-1024K 23 +VALUE Ascend-Data-Svc Switched-1088K 24 +VALUE Ascend-Data-Svc Switched-1152K 25 +VALUE Ascend-Data-Svc Switched-1216K 26 +VALUE Ascend-Data-Svc Switched-1280K 27 +VALUE Ascend-Data-Svc Switched-1344K 28 +VALUE Ascend-Data-Svc Switched-1408K 29 +VALUE Ascend-Data-Svc Switched-1472K 30 +VALUE Ascend-Data-Svc Switched-1600K 31 +VALUE Ascend-Data-Svc Switched-1664K 32 +VALUE Ascend-Data-Svc Switched-1728K 33 +VALUE Ascend-Data-Svc Switched-1792K 34 +VALUE Ascend-Data-Svc Switched-1856K 35 +VALUE Ascend-Data-Svc Switched-1920K 36 +VALUE Ascend-Data-Svc Switched-inherited 37 +VALUE Ascend-Data-Svc Switched-restricted-bearer-x30 38 +VALUE Ascend-Data-Svc Switched-clear-bearer-v110 39 +VALUE Ascend-Data-Svc Switched-restricted-64-x30 40 +VALUE Ascend-Data-Svc Switched-clear-56-v110 41 +VALUE Ascend-Data-Svc Switched-modem 42 +VALUE Ascend-Data-Svc Switched-atmodem 43 +VALUE Ascend-Data-Svc Nailed-56KR 1 +VALUE Ascend-Data-Svc Nailed-64K 2 +VALUE Ascend-Force-56 Force-56-No 0 +VALUE Ascend-Force-56 Force-56-Yes 1 +VALUE Ascend-PW-Lifetime Lifetime-In-Days 0 +VALUE Ascend-PW-Warntime Days-Of-Warning 0 +VALUE Ascend-PPP-VJ-1172 PPP-VJ-1172 1 +VALUE Ascend-PPP-VJ-Slot-Comp VJ-Slot-Comp-No 1 +VALUE Ascend-Require-Auth Not-Require-Auth 0 +VALUE Ascend-Require-Auth Require-Auth 1 +VALUE Ascend-Token-Immediate Tok-Imm-No 0 +VALUE Ascend-Token-Immediate Tok-Imm-Yes 1 +VALUE Ascend-DBA-Monitor DBA-Transmit 0 +VALUE Ascend-DBA-Monitor DBA-Transmit-Recv 1 +VALUE Ascend-DBA-Monitor DBA-None 2 +VALUE Ascend-FR-Type Ascend-FR-DTE 0 +VALUE Ascend-FR-Type Ascend-FR-DCE 1 +VALUE Ascend-FR-Type Ascend-FR-NNI 2 +VALUE Ascend-FR-Link-Mgt Ascend-FR-No-Link-Mgt 0 +VALUE Ascend-FR-Link-Mgt Ascend-FR-T1-617D 1 +VALUE Ascend-FR-Link-Mgt Ascend-FR-Q-933A 2 +VALUE Ascend-FR-LinkUp Ascend-LinkUp-Default 0 +VALUE Ascend-FR-LinkUp Ascend-LinkUp-AlwaysUp 1 +VALUE Ascend-Multicast-Client Multicast-No 0 +VALUE Ascend-Multicast-Client Multicast-Yes 1 +VALUE Ascend-User-Acct-Type Ascend-User-Acct-None 0 +VALUE Ascend-User-Acct-Type Ascend-User-Acct-User 1 +VALUE Ascend-User-Acct-Type Ascend-User-Acct-User-Default 2 +VALUE Ascend-User-Acct-Base Base-10 0 +VALUE Ascend-User-Acct-Base Base-16 1 +VALUE Ascend-DHCP-Reply DHCP-Reply-No 0 +VALUE Ascend-DHCP-Reply DHCP-Reply-Yes 1 +VALUE Ascend-Client-Assign-DNS DNS-Assign-No 0 +VALUE Ascend-Client-Assign-DNS DNS-Assign-Yes 1 +VALUE Ascend-Event-Type Ascend-ColdStart 1 +VALUE Ascend-Event-Type Ascend-Session-Event 2 +VALUE Ascend-BACP-Enable BACP-No 0 +VALUE Ascend-BACP-Enable BACP-Yes 1 +VALUE Ascend-Dialout-Allowed Dialout-Not-Allowed 0 +VALUE Ascend-Dialout-Allowed Dialout-Allowed 1 +VALUE Ascend-Shared-Profile-Enable Shared-Profile-No 0 +VALUE Ascend-Shared-Profile-Enable Shared-Profile-Yes 1 +VALUE Ascend-Temporary-Rtes Temp-Rtes-No 0 +VALUE Ascend-Temporary-Rtes Temp-Rtes-Yes 1 diff --git a/src/plugins/vbng/etc/dictionary.compat b/src/plugins/vbng/etc/dictionary.compat new file mode 100644 index 0000000..4c85ea8 --- /dev/null +++ b/src/plugins/vbng/etc/dictionary.compat @@ -0,0 +1,47 @@ +# +# Obsolete names for backwards compatibility with older users files. +# Move the $INCLUDE in the main dictionary file to the end if you want +# these names to be used in the "details" logfile. +# +ATTRIBUTE Client-Id 4 ipaddr +ATTRIBUTE Client-Port-Id 5 integer +ATTRIBUTE User-Service-Type 6 integer +ATTRIBUTE Framed-Address 8 ipaddr +ATTRIBUTE Framed-Netmask 9 ipaddr +ATTRIBUTE Framed-Filter-Id 11 string +ATTRIBUTE Login-Host 14 ipaddr +ATTRIBUTE Login-Port 16 integer +ATTRIBUTE Old-Password 17 string +ATTRIBUTE Port-Message 18 string +ATTRIBUTE Dialback-No 19 string +ATTRIBUTE Dialback-Name 20 string +ATTRIBUTE Challenge-State 24 string +VALUE Framed-Compression Van-Jacobsen-TCP-IP 1 +VALUE Framed-Compression VJ-TCP-IP 1 +VALUE Service-Type Shell-User 6 +VALUE Auth-Type Unix 1 +VALUE Service-Type Dialback-Login-User 3 +VALUE Service-Type Dialback-Framed-User 4 + +# +# For compatibility with MERIT users files. +# +ATTRIBUTE NAS-Port 5 integer +ATTRIBUTE Login-Host 14 ipaddr +ATTRIBUTE Login-Callback-Number 19 string +ATTRIBUTE Framed-Callback-Id 20 string +ATTRIBUTE Client-Port-DNIS 30 string +ATTRIBUTE Caller-ID 31 string +VALUE Service-Type Login 1 +VALUE Service-Type Framed 2 +VALUE Service-Type Callback-Login 3 +VALUE Service-Type Callback-Framed 4 +VALUE Service-Type Exec-User 7 + +# +# For compatibility with ESVA RADIUS, Old Cistron RADIUS +# +ATTRIBUTE Session 1034 integer +ATTRIBUTE User-Name-Is-Star 1035 integer +VALUE User-Name-Is-Star No 0 +VALUE User-Name-Is-Star Yes 1 diff --git a/src/plugins/vbng/etc/dictionary.dhcp b/src/plugins/vbng/etc/dictionary.dhcp new file mode 100644 index 0000000..cf32934 --- /dev/null +++ b/src/plugins/vbng/etc/dictionary.dhcp @@ -0,0 +1,440 @@ +# -*- text -*- +# Copyright (C) 2011 The FreeRADIUS Server project and contributors +############################################################################## +# +# DHCP to RADUS gateway dictionary. +# +# http://www.iana.org/assignments/bootp-dhcp-parameters +# +# Also http://www.networksorcery.com/enp/protocol/bootp/options.htm +# +# http://www.bind9.net/rfc-dhcp +# +# $Id: 73632c57d3860bb30749a1df4dad2320d5f79f31 $ +# +############################################################################## + +# + +# This is really Apollo's number, but since they're out of business, +# I don't think they'll be needing this. +# +# HP owns the Apollo assets, but let's not worry about that. +# +# The vendor codes are 2 octets, because we need 256 numbers +# for the base DHCP options, PLUS a few for the DHCP headers, +# which aren't in option format. +# +# On top of that, a number of options are really TLV's. +# We need to be able to understand them, too. +# +VENDOR DHCP 54 format=2,1 + +BEGIN-VENDOR DHCP + +ATTRIBUTE DHCP-Opcode 256 byte +ATTRIBUTE DHCP-Hardware-Type 257 byte +ATTRIBUTE DHCP-Hardware-Address-Length 258 byte +ATTRIBUTE DHCP-Hop-Count 259 byte +ATTRIBUTE DHCP-Transaction-Id 260 integer +ATTRIBUTE DHCP-Number-of-Seconds 261 short +ATTRIBUTE DHCP-Flags 262 short +ATTRIBUTE DHCP-Client-IP-Address 263 ipaddr +ATTRIBUTE DHCP-Your-IP-Address 264 ipaddr +ATTRIBUTE DHCP-Server-IP-Address 265 ipaddr +ATTRIBUTE DHCP-Gateway-IP-Address 266 ipaddr +ATTRIBUTE DHCP-Client-Hardware-Address 267 ether # 16 octets +ATTRIBUTE DHCP-Server-Host-Name 268 string # 64 octets +ATTRIBUTE DHCP-Boot-Filename 269 string # 128 octets + +ATTRIBUTE DHCP-Relay-To-IP-Address 270 ipaddr +ATTRIBUTE DHCP-Relay-Max-Hop-Count 271 integer + +# This is copied from the request packet, giaddr, and +# added to the reply packet by the server core. +ATTRIBUTE DHCP-Relay-IP-Address 272 ipaddr + +VALUE DHCP-Flags Broadcast 0x8000 + +VALUE DHCP-Hardware-Type Ethernet 1 +VALUE DHCP-Hardware-Type Experiemental-Ethernet 2 +VALUE DHCP-Hardware-Type AX.25 3 +VALUE DHCP-Hardware-Type Proteon-Token-Ring 4 +VALUE DHCP-Hardware-Type Chaos 5 +VALUE DHCP-Hardware-Type IEEE-802 6 +VALUE DHCP-Hardware-Type Arcnet 7 +VALUE DHCP-Hardware-Type Hyperchannel 8 +VALUE DHCP-Hardware-Type Lanstar 9 +VALUE DHCP-Hardware-Type Autonet-Short-Address 10 +VALUE DHCP-Hardware-Type LocalTalk 11 +VALUE DHCP-Hardware-Type LocalNet 12 +VALUE DHCP-Hardware-Type Ultra-Link 13 +VALUE DHCP-Hardware-Type SMDS 14 +VALUE DHCP-Hardware-Type Frame-Relay 15 +VALUE DHCP-Hardware-Type ATM-16 16 +VALUE DHCP-Hardware-Type HDLC 17 +VALUE DHCP-Hardware-Type Fibre-Channel 18 +VALUE DHCP-Hardware-Type ATM-19 19 +VALUE DHCP-Hardware-Type Serial-Line 20 +VALUE DHCP-Hardware-Type ATM-21 21 +VALUE DHCP-Hardware-Type MIL-STD-188-220 22 +VALUE DHCP-Hardware-Type Metricom 23 +VALUE DHCP-Hardware-Type IEEE-1394 24 +VALUE DHCP-Hardware-Type MAPOS 25 +VALUE DHCP-Hardware-Type Twinaxial 26 +VALUE DHCP-Hardware-Type EUI-64 27 +VALUE DHCP-Hardware-Type HIPARP 28 +VALUE DHCP-Hardware-Type IP-Over-ISO-7816-3 29 +VALUE DHCP-Hardware-Type ARPSec 30 +VALUE DHCP-Hardware-Type IPSec-Tunnel 31 +VALUE DHCP-Hardware-Type Infiniband 32 +VALUE DHCP-Hardware-Type CAI-TIA-102 33 + +############################################################################## +# +# DHCP Options, with comments. For now, many are "octets", +# as FreeRADIUS doesn't handle complex data structures. +# +############################################################################## + +#ATTRIBUTE DHCP-Pad 0 octets +ATTRIBUTE DHCP-Subnet-Mask 1 ipaddr +# Time Offset in twos-complement notation. +ATTRIBUTE DHCP-Time-Offset 2 integer +ATTRIBUTE DHCP-Router-Address 3 ipaddr array +ATTRIBUTE DHCP-Time-Server 4 ipaddr array +ATTRIBUTE DHCP-IEN-116-Name-Server 5 ipaddr array +ATTRIBUTE DHCP-Domain-Name-Server 6 ipaddr array +# Logging-Server addresses +ATTRIBUTE DHCP-Log-Server 7 ipaddr array +ATTRIBUTE DHCP-Quotes-Server 8 ipaddr array +ATTRIBUTE DHCP-LPR-Server 9 ipaddr array +ATTRIBUTE DHCP-Impress-Server 10 ipaddr array +ATTRIBUTE DHCP-RLP-Server 11 ipaddr array +# Hostname string +ATTRIBUTE DHCP-Hostname 12 string +# Size of boot file in 512 byte +ATTRIBUTE DHCP-Boot-File-Size 13 short +# Client to dump and name +ATTRIBUTE DHCP-Merit-Dump-File 14 octets +ATTRIBUTE DHCP-Domain-Name 15 string +ATTRIBUTE DHCP-Swap-Server 16 ipaddr +# Path name for root disk +ATTRIBUTE DHCP-Root-Path 17 string +ATTRIBUTE DHCP-Bootp-Extensions-Path 18 string +ATTRIBUTE DHCP-IP-Forward-Enable 19 byte +ATTRIBUTE DHCP-Source-Route-Enable 20 byte +# Routing Policy Filters +ATTRIBUTE DHCP-Policy-Filter 21 octets +ATTRIBUTE DHCP-Max-Datagram-Reassembly-Sz 22 short +ATTRIBUTE DHCP-Default-IP-TTL 23 octets +ATTRIBUTE DHCP-Path-MTU-Aging-Timeout 24 integer +ATTRIBUTE DHCP-Path-MTU-Plateau-Table 25 short array +ATTRIBUTE DHCP-Interface-MTU-Size 26 short +ATTRIBUTE DHCP-All-Subnets-Are-Local 27 byte +ATTRIBUTE DHCP-Broadcast-Address 28 ipaddr +ATTRIBUTE DHCP-Perform-Mask-Discovery 29 byte +ATTRIBUTE DHCP-Provide-Mask-To-Others 30 byte +ATTRIBUTE DHCP-Perform-Router-Discovery 31 byte +ATTRIBUTE DHCP-Router-Solicitation-Address 32 ipaddr +# first is destination address, second is router. +ATTRIBUTE DHCP-Static-Routes 33 ipaddr array +ATTRIBUTE DHCP-Trailer-Encapsulation 34 byte +ATTRIBUTE DHCP-ARP-Cache-Timeout 35 integer +ATTRIBUTE DHCP-Ethernet-Encapsulation 36 byte +ATTRIBUTE DHCP-Default-TCP-TTL 37 byte +ATTRIBUTE DHCP-Keep-Alive-Interval 38 integer +ATTRIBUTE DHCP-Keep-Alive-Garbage 39 byte +ATTRIBUTE DHCP-NIS-Domain-Name 40 string +ATTRIBUTE DHCP-NIS-Servers 41 ipaddr array +ATTRIBUTE DHCP-NTP-Servers 42 ipaddr array +# N Vendor Specific Information +ATTRIBUTE DHCP-Vendor 43 octets # tlv +ATTRIBUTE DHCP-NETBIOS-Name-Servers 44 ipaddr array +ATTRIBUTE DHCP-NETBIOS-Dgm-Dist-Servers 45 ipaddr array +ATTRIBUTE DHCP-NETBIOS-Node-Type 46 byte +# N NETBIOS Scope +ATTRIBUTE DHCP-NETBIOS 47 octets +ATTRIBUTE DHCP-X-Window-Font-Server 48 ipaddr array +ATTRIBUTE DHCP-X-Window-Display-Mgr 49 ipaddr array +ATTRIBUTE DHCP-Requested-IP-Address 50 ipaddr +ATTRIBUTE DHCP-IP-Address-Lease-Time 51 integer +# Overload "sname" or "file" +ATTRIBUTE DHCP-Overload 52 byte +ATTRIBUTE DHCP-Message-Type 53 byte +ATTRIBUTE DHCP-DHCP-Server-Identifier 54 ipaddr + +# Array of 1-byte numbers indicating which options the client +# would like to see in the response. +ATTRIBUTE DHCP-Parameter-Request-List 55 byte array +ATTRIBUTE DHCP-DHCP-Error-Message 56 octets +ATTRIBUTE DHCP-DHCP-Maximum-Msg-Size 57 short +ATTRIBUTE DHCP-Renewal-Time 58 integer +ATTRIBUTE DHCP-Rebinding-Time 59 integer +ATTRIBUTE DHCP-Vendor-Class-Identifier 60 string + +# Client Identifier +# First octets is DHCP-Hardware-Type, rest are type-specific data, +# e.g. MAC address. +ATTRIBUTE DHCP-Client-Identifier 61 ether +ATTRIBUTE DHCP-Netware-Domain-Name 62 octets +ATTRIBUTE DHCP-Netware-Sub-Options 63 octets +ATTRIBUTE DHCP-NIS-Client-Domain-Name 64 octets +ATTRIBUTE DHCP-NIS-Server-Address 65 ipaddr +ATTRIBUTE DHCP-TFTP-Server-Name 66 string +ATTRIBUTE DHCP-Boot-File-Name 67 string +# Home Agent Addresses +ATTRIBUTE DHCP-Home-Agent-Address 68 octets +ATTRIBUTE DHCP-SMTP-Server-Address 69 ipaddr array +ATTRIBUTE DHCP-POP3-Server-Address 70 ipaddr array +ATTRIBUTE DHCP-NNTP-Server-Address 71 ipaddr array +ATTRIBUTE DHCP-WWW-Server-Address 72 ipaddr array +ATTRIBUTE DHCP-Finger-Server-Address 73 ipaddr array +ATTRIBUTE DHCP-IRC-Server-Address 74 ipaddr array +ATTRIBUTE DHCP-StreetTalk-Server-Address 75 ipaddr array +ATTRIBUTE DHCP-STDA-Server-Address 76 ipaddr array +# User Class Information +ATTRIBUTE DHCP-User-Class 77 octets +# directory agent information +ATTRIBUTE DHCP-Directory-Agent 78 octets +# service location agent scope +ATTRIBUTE DHCP-Service-Scope 79 octets +# Rapid Commit +ATTRIBUTE DHCP-Rapid-Commit 80 octets +# Fully Qualified Domain Name +ATTRIBUTE DHCP-Client-FQDN 81 string +# Relay Agent Information +ATTRIBUTE DHCP-Relay-Agent-Information 82 tlv + +ATTRIBUTE DHCP-Agent-Circuit-Id 82.1 octets +ATTRIBUTE DHCP-Agent-Remote-Id 82.2 octets + +ATTRIBUTE DHCP-Relay-Circuit-Id 82.1 octets +ATTRIBUTE DHCP-Relay-Remote-Id 82.2 octets + +# 3 is reserved and shouldn't be used for anything +ATTRIBUTE DHCP-Docsis-Device-Class 82.4 integer +ATTRIBUTE DHCP-Relay-Link-Selection 82.5 ipaddr +ATTRIBUTE DHCP-Subscriber-Id 82.6 string + +# AGH! RADIUS inside of DHCP! +ATTRIBUTE DHCP-RADIUS-Attributes 82.7 octets + +# Horribly complicated +ATTRIBUTE DHCP-Authentication-Information 82.8 octets +ATTRIBUTE DHCP-Vendor-Specific-Information 82.9 octets +ATTRIBUTE DHCP-Relay-Agent-Flags 82.10 byte +ATTRIBUTE DHCP-Server-Identifier-Override 82.11 ipaddr + +# Internet Storage Name Service +ATTRIBUTE DHCP-iSNS 83 octets +# Novell Directory Services +ATTRIBUTE DHCP-NDS-Servers 85 octets +# Novell Directory Services +ATTRIBUTE DHCP-NDS-Tree-Name 86 octets +# Novell Directory Services +ATTRIBUTE DHCP-NDS-Context 87 octets +# Authentication +ATTRIBUTE DHCP-Authentication 90 octets + +ATTRIBUTE DHCP-Client-Last-Txn-Time 91 octets + +ATTRIBUTE DHCP-associated-ip 92 octets +# Client System Architecture +ATTRIBUTE DHCP-Client-System 93 octets +# Client Network Device Interface +ATTRIBUTE DHCP-Client-NDI 94 octets +# Lightweight Directory Access Protocol +ATTRIBUTE DHCP-LDAP 95 octets +# UUID/GUID-based Client Identifier +ATTRIBUTE DHCP-UUID/GUID 97 octets +# Open Group's User Authentication +ATTRIBUTE DHCP-User-Auth 98 octets +# NetInfo Parent-Server Address +ATTRIBUTE DHCP-Netinfo-Address 112 octets +# NetInfo Parent-Server Tag +ATTRIBUTE DHCP-Netinfo-Tag 113 octets +# URL +ATTRIBUTE DHCP-URL 114 octets +# DHCP Auto-Configuration +ATTRIBUTE DHCP-Auto-Config 116 byte +# Name Service Search +ATTRIBUTE DHCP-Name-Service-Search 117 octets +# Subnet Selection Option +ATTRIBUTE DHCP-Subnet-Selection-Option 118 octets +# DNS domain serach list +ATTRIBUTE DHCP-Domain-Search 119 octets +# SIP-Servers DHCP Option +ATTRIBUTE DHCP-SIP-Servers-DHCP-Option 120 octets +# Classless Static Route Option +ATTRIBUTE DHCP-Classless-Static-Route 121 octets +# CableLabs Client Configuration +ATTRIBUTE DHCP-CCC 122 octets +# 16 GeoConf Option +ATTRIBUTE DHCP-GeoConf-Option 123 octets + +# Vendor Class +# +# String name that defines the vendor space used for the TLV's +# in option 125. +# +ATTRIBUTE DHCP-V-I-Vendor-Class 124 octets +# Vendor-Specific +ATTRIBUTE DHCP-V-I-Vendor-Specific 125 octets # tlv +ATTRIBUTE DHCP-Etherboot 128 ether +# (for IP Phone software load) +ATTRIBUTE DHCP-TFTP-Server-IP-Address 128 octets + +ATTRIBUTE DHCP-Call-Server-IP-address 129 octets + +ATTRIBUTE DHCP-Ethernet-Interface 130 octets + +ATTRIBUTE DHCP-Vendor-Discrimination-Str 130 octets + +ATTRIBUTE DHCP-Remote-Stats-Svr-IP-Address 131 octets + +ATTRIBUTE DHCP-IEEE-802.1Q-L2-Priority 132 octets + +ATTRIBUTE DHCP-IEEE-802.1P-VLAN-ID 133 octets + +ATTRIBUTE DHCP-Diffserv-Code-Point 134 octets + +ATTRIBUTE DHCP-HTTP-Proxy 135 octets + +ATTRIBUTE DHCP-Cisco-TFTP-Server-IP-Addresses 150 ipaddr array + +ATTRIBUTE DHCP-End-Of-Options 255 byte + +VALUE DHCP-Opcode Client-Message 1 +VALUE DHCP-Opcode Server-Message 2 + +VALUE DHCP-Message-Type DHCP-Do-Not-Respond 0 +VALUE DHCP-Message-Type DHCP-Discover 1 +VALUE DHCP-Message-Type DHCP-Offer 2 +VALUE DHCP-Message-Type DHCP-Request 3 +VALUE DHCP-Message-Type DHCP-Decline 4 +VALUE DHCP-Message-Type DHCP-Ack 5 +VALUE DHCP-Message-Type DHCP-NAK 6 +VALUE DHCP-Message-Type DHCP-Release 7 +VALUE DHCP-Message-Type DHCP-Inform 8 +VALUE DHCP-Message-Type DHCP-Force-Renew 9 + +VALUE DHCP-Parameter-Request-List DHCP-Subnet-Mask 1 +VALUE DHCP-Parameter-Request-List DHCP-Time-Offset 2 +VALUE DHCP-Parameter-Request-List DHCP-Router-Address 3 +VALUE DHCP-Parameter-Request-List DHCP-Time-Server 4 +VALUE DHCP-Parameter-Request-List DHCP-IEN-116-Name-Server 5 +VALUE DHCP-Parameter-Request-List DHCP-Domain-Name-Server 6 +VALUE DHCP-Parameter-Request-List DHCP-Log-Server 7 +VALUE DHCP-Parameter-Request-List DHCP-Quotes-Server 8 +VALUE DHCP-Parameter-Request-List DHCP-LPR-Server 9 +VALUE DHCP-Parameter-Request-List DHCP-Impress-Server 10 +VALUE DHCP-Parameter-Request-List DHCP-RLP-Server 11 +VALUE DHCP-Parameter-Request-List DHCP-Hostname 12 +VALUE DHCP-Parameter-Request-List DHCP-Boot-File-Size 13 +VALUE DHCP-Parameter-Request-List DHCP-Merit-Dump-File 14 +VALUE DHCP-Parameter-Request-List DHCP-Domain-Name 15 +VALUE DHCP-Parameter-Request-List DHCP-Swap-Server 16 +VALUE DHCP-Parameter-Request-List DHCP-Root-Path 17 +VALUE DHCP-Parameter-Request-List DHCP-Bootp-Extensions-Path 18 +VALUE DHCP-Parameter-Request-List DHCP-IP-Forward-Enable 19 +VALUE DHCP-Parameter-Request-List DHCP-Source-Route-Enable 20 +VALUE DHCP-Parameter-Request-List DHCP-Policy-Filter 21 +VALUE DHCP-Parameter-Request-List DHCP-Max-Datagram-Reassembly-Sz 22 +VALUE DHCP-Parameter-Request-List DHCP-Default-IP-TTL 23 +VALUE DHCP-Parameter-Request-List DHCP-Path-MTU-Aging-Timeout 24 +VALUE DHCP-Parameter-Request-List DHCP-Path-MTU-Plateau-Table 25 +VALUE DHCP-Parameter-Request-List DHCP-Interface-MTU-Size 26 +VALUE DHCP-Parameter-Request-List DHCP-All-Subnets-Are-Local 27 +VALUE DHCP-Parameter-Request-List DHCP-Broadcast-Address 28 +VALUE DHCP-Parameter-Request-List DHCP-Perform-Mask-Discovery 29 +VALUE DHCP-Parameter-Request-List DHCP-Provide-Mask-To-Others 30 +VALUE DHCP-Parameter-Request-List DHCP-Perform-Router-Discovery 31 +VALUE DHCP-Parameter-Request-List DHCP-Router-Solicitation-Address 32 +VALUE DHCP-Parameter-Request-List DHCP-Static-Routes 33 +VALUE DHCP-Parameter-Request-List DHCP-Trailer-Encapsulation 34 +VALUE DHCP-Parameter-Request-List DHCP-ARP-Cache-Timeout 35 +VALUE DHCP-Parameter-Request-List DHCP-Ethernet-Encapsulation 36 +VALUE DHCP-Parameter-Request-List DHCP-Default-TCP-TTL 37 +VALUE DHCP-Parameter-Request-List DHCP-Keep-Alive-Interval 38 +VALUE DHCP-Parameter-Request-List DHCP-Keep-Alive-Garbage 39 +VALUE DHCP-Parameter-Request-List DHCP-NIS-Domain-Name 40 +VALUE DHCP-Parameter-Request-List DHCP-NIS-Servers 41 +VALUE DHCP-Parameter-Request-List DHCP-NTP-Servers 42 +VALUE DHCP-Parameter-Request-List DHCP-Vendor 43 +VALUE DHCP-Parameter-Request-List DHCP-NETBIOS-Name-Servers 44 +VALUE DHCP-Parameter-Request-List DHCP-NETBIOS-Dgm-Dist-Servers 45 +VALUE DHCP-Parameter-Request-List DHCP-NETBIOS-Node-Type 46 +VALUE DHCP-Parameter-Request-List DHCP-NETBIOS 47 +VALUE DHCP-Parameter-Request-List DHCP-X-Window-Font-Server 48 +VALUE DHCP-Parameter-Request-List DHCP-X-Window-Display-Mgr 49 +VALUE DHCP-Parameter-Request-List DHCP-Requested-IP-Address 50 +VALUE DHCP-Parameter-Request-List DHCP-IP-Address-Lease-Time 51 +VALUE DHCP-Parameter-Request-List DHCP-Overload 52 +VALUE DHCP-Parameter-Request-List DHCP-Message-Type 53 +VALUE DHCP-Parameter-Request-List DHCP-DHCP-Server-Identifier 54 +VALUE DHCP-Parameter-Request-List DHCP-Parameter-Request-List 55 +VALUE DHCP-Parameter-Request-List DHCP-DHCP-Error-Message 56 +VALUE DHCP-Parameter-Request-List DHCP-DHCP-Maximum-Msg-Size 57 +VALUE DHCP-Parameter-Request-List DHCP-Renewal-Time 58 +VALUE DHCP-Parameter-Request-List DHCP-Rebinding-Time 59 +VALUE DHCP-Parameter-Request-List DHCP-Class-Identifier 60 +VALUE DHCP-Parameter-Request-List DHCP-Client-Identifier 61 +VALUE DHCP-Parameter-Request-List DHCP-Netware-Domain-Name 62 +VALUE DHCP-Parameter-Request-List DHCP-Netware-Sub-Options 63 +VALUE DHCP-Parameter-Request-List DHCP-NIS-Client-Domain-Name 64 +VALUE DHCP-Parameter-Request-List DHCP-NIS-Server-Address 65 +VALUE DHCP-Parameter-Request-List DHCP-TFTP-Server-Name 66 +VALUE DHCP-Parameter-Request-List DHCP-Boot-File-Name 67 +VALUE DHCP-Parameter-Request-List DHCP-Home-Agent-Address 68 +VALUE DHCP-Parameter-Request-List DHCP-SMTP-Server-Address 69 +VALUE DHCP-Parameter-Request-List DHCP-POP3-Server-Address 70 +VALUE DHCP-Parameter-Request-List DHCP-NNTP-Server-Address 71 +VALUE DHCP-Parameter-Request-List DHCP-WWW-Server-Address 72 +VALUE DHCP-Parameter-Request-List DHCP-Finger-Server-Address 73 +VALUE DHCP-Parameter-Request-List DHCP-IRC-Server-Address 74 +VALUE DHCP-Parameter-Request-List DHCP-StreetTalk-Server-Address 75 +VALUE DHCP-Parameter-Request-List DHCP-STDA-Server-Address 76 +VALUE DHCP-Parameter-Request-List DHCP-User-Class 77 +VALUE DHCP-Parameter-Request-List DHCP-Directory-Agent 78 +VALUE DHCP-Parameter-Request-List DHCP-Service-Scope 79 +VALUE DHCP-Parameter-Request-List DHCP-Rapid-Commit 80 +VALUE DHCP-Parameter-Request-List DHCP-Client-FQDN 81 +VALUE DHCP-Parameter-Request-List DHCP-Relay-Agent-Information 82 +VALUE DHCP-Parameter-Request-List DHCP-iSNS 83 +VALUE DHCP-Parameter-Request-List DHCP-NDS-Servers 85 +VALUE DHCP-Parameter-Request-List DHCP-NDS-Tree-Name 86 +VALUE DHCP-Parameter-Request-List DHCP-NDS-Context 87 +VALUE DHCP-Parameter-Request-List DHCP-Authentication 90 +VALUE DHCP-Parameter-Request-List DHCP-Client-Last-Txn-Time 91 +VALUE DHCP-Parameter-Request-List DHCP-associated-ip 92 +VALUE DHCP-Parameter-Request-List DHCP-Client-System 93 +VALUE DHCP-Parameter-Request-List DHCP-Client-NDI 94 +VALUE DHCP-Parameter-Request-List DHCP-LDAP 95 +VALUE DHCP-Parameter-Request-List DHCP-UUID/GUID 97 +VALUE DHCP-Parameter-Request-List DHCP-User-Auth 98 +VALUE DHCP-Parameter-Request-List DHCP-Netinfo-Address 112 +VALUE DHCP-Parameter-Request-List DHCP-Netinfo-Tag 113 +VALUE DHCP-Parameter-Request-List DHCP-URL 114 +VALUE DHCP-Parameter-Request-List DHCP-Auto-Config 116 +VALUE DHCP-Parameter-Request-List DHCP-Name-Service-Search 117 +VALUE DHCP-Parameter-Request-List DHCP-Subnet-Selection-Option 118 +VALUE DHCP-Parameter-Request-List DHCP-Domain-Search 119 +VALUE DHCP-Parameter-Request-List DHCP-SIP-Servers-DHCP-Option 120 +VALUE DHCP-Parameter-Request-List DHCP-Classless-Static-Route 121 +VALUE DHCP-Parameter-Request-List DHCP-CCC 122 +VALUE DHCP-Parameter-Request-List DHCP-GeoConf-Option 123 +VALUE DHCP-Parameter-Request-List DHCP-V-I-Vendor-Class 124 +VALUE DHCP-Parameter-Request-List DHCP-V-I-Vendor-Specific 125 +VALUE DHCP-Parameter-Request-List DHCP-Etherboot 128 +VALUE DHCP-Parameter-Request-List DHCP-TFTP-Server-IP-Address 128 +VALUE DHCP-Parameter-Request-List DHCP-Call-Server-IP-address 129 +VALUE DHCP-Parameter-Request-List DHCP-Ethernet-Interface 130 +VALUE DHCP-Parameter-Request-List DHCP-Vendor-Discrimination-Str 130 +VALUE DHCP-Parameter-Request-List DHCP-Remote-Stats-Svr-IP-Address 131 +VALUE DHCP-Parameter-Request-List DHCP-IEEE-802.1P-VLAN-ID 132 +VALUE DHCP-Parameter-Request-List DHCP-IEEE-802.1Q-L2-Priority 133 +VALUE DHCP-Parameter-Request-List DHCP-Diffserv-Code-Point 134 +VALUE DHCP-Parameter-Request-List DHCP-HTTP-Proxy 135 + +END-VENDOR DHCP diff --git a/src/plugins/vbng/etc/dictionary.merit b/src/plugins/vbng/etc/dictionary.merit new file mode 100644 index 0000000..7d675e5 --- /dev/null +++ b/src/plugins/vbng/etc/dictionary.merit @@ -0,0 +1,17 @@ +# +# Experimental extensions, configuration only (for check-items) +# Names/numbers as per the MERIT extensions (if possible). +# +ATTRIBUTE NAS-Identifier 32 string +ATTRIBUTE Proxy-State 33 string +ATTRIBUTE Login-LAT-Service 34 string +ATTRIBUTE Login-LAT-Node 35 string +ATTRIBUTE Login-LAT-Group 36 string +ATTRIBUTE Framed-AppleTalk-Link 37 integer +ATTRIBUTE Framed-AppleTalk-Network 38 integer +ATTRIBUTE Framed-AppleTalk-Zone 39 string +ATTRIBUTE Acct-Input-Packets 47 integer +ATTRIBUTE Acct-Output-Packets 48 integer +# 8 is a MERIT extension. +VALUE Service-Type Authenticate-Only 8 + diff --git a/src/plugins/vbng/etc/dictionary.sip b/src/plugins/vbng/etc/dictionary.sip new file mode 100644 index 0000000..149fa4c --- /dev/null +++ b/src/plugins/vbng/etc/dictionary.sip @@ -0,0 +1,77 @@ +# +# Updated 97/06/13 to livingston-radius-2.01 miquels@cistron.nl +# +# This file contains dictionary translations for parsing +# requests and generating responses. All transactions are +# composed of Attribute/Value Pairs. The value of each attribute +# is specified as one of 4 data types. Valid data types are: +# +# string - 0-253 octets +# ipaddr - 4 octets in network byte order +# integer - 32 bit value in big endian order (high byte first) +# date - 32 bit value in big endian order - seconds since +# 00:00:00 GMT, Jan. 1, 1970 +# +# Enumerated values are stored in the user file with dictionary +# VALUE translations for easy administration. +# +# Example: +# +# ATTRIBUTE VALUE +# --------------- ----- +# Framed-Protocol = PPP +# 7 = 1 (integer encoding) +# + +# +# Experimental SIP Attributes/Values (draft-sterman-aaa-sip-00.txt etc) +# +ATTRIBUTE Sip-Method 101 integer +ATTRIBUTE Sip-Response-Code 102 integer +ATTRIBUTE Sip-CSeq 103 string +ATTRIBUTE Sip-To-Tag 104 string +ATTRIBUTE Sip-From-Tag 105 string +ATTRIBUTE Sip-Branch-ID 106 string +ATTRIBUTE Sip-Translated-Request-URI 107 string +ATTRIBUTE Sip-Source-IP-Address 108 ipaddr +ATTRIBUTE Sip-Source-Port 109 integer +ATTRIBUTE Sip-User-ID 110 string +ATTRIBUTE Sip-User-Realm 111 string +ATTRIBUTE Sip-User-Nonce 112 string +ATTRIBUTE Sip-User-Method 113 string +ATTRIBUTE Sip-User-Digest-URI 114 string +ATTRIBUTE Sip-User-Nonce-Count 115 string +ATTRIBUTE Sip-User-QOP 116 string +ATTRIBUTE Sip-User-Opaque 117 string +ATTRIBUTE Sip-User-Response 118 string +ATTRIBUTE Sip-User-CNonce 119 string +ATTRIBUTE Sip-URI-User 208 string +ATTRIBUTE Sip-Req-URI 210 string +ATTRIBUTE Sip-CC 212 string +ATTRIBUTE Sip-RPId 213 string +ATTRIBUTE Digest-Response 206 string +ATTRIBUTE Digest-Attributes 207 string +ATTRIBUTE Digest-Realm 1063 string +ATTRIBUTE Digest-Nonce 1064 string +ATTRIBUTE Digest-Method 1065 string +ATTRIBUTE Digest-URI 1066 string +ATTRIBUTE Digest-QOP 1067 string +ATTRIBUTE Digest-Algorithm 1068 string +ATTRIBUTE Digest-Body-Digest 1069 string +ATTRIBUTE Digest-CNonce 1070 string +ATTRIBUTE Digest-Nonce-Count 1071 string +ATTRIBUTE Digest-User-Name 1072 string + +VALUE Service-Type SIP 15 + +VALUE Sip-Method Other 0 +VALUE Sip-Method Invite 1 +VALUE Sip-Method Cancel 2 +VALUE Sip-Method Ack 3 +VALUE Sip-Method Bye 4 + +VALUE Sip-Response-Code Other 0 +VALUE Sip-Response-Code Invite 1 +VALUE Sip-Response-Code Cancel 2 +VALUE Sip-Response-Code Ack 3 +VALUE Sip-Response-Code Bye 4 diff --git a/src/plugins/vbng/etc/issue b/src/plugins/vbng/etc/issue new file mode 100644 index 0000000..6254487 --- /dev/null +++ b/src/plugins/vbng/etc/issue @@ -0,0 +1,5 @@ +(\I) +----------------------------------------------------- +\S \R (\N) (port \L) +----------------------------------------------------- + diff --git a/src/plugins/vbng/etc/port-id-map b/src/plugins/vbng/etc/port-id-map new file mode 100644 index 0000000..9088a0b --- /dev/null +++ b/src/plugins/vbng/etc/port-id-map @@ -0,0 +1,24 @@ +# +# port-id-map +# +# This file describes the ttyname to port id mapping. The port id +# is reported as part of a RADIUS authentication or accouting request. +# +#ttyname (as returned by ttyname(3)) port-id +/dev/tty1 1 +/dev/tty2 2 +/dev/tty3 3 +/dev/tty4 4 +/dev/tty5 5 +/dev/tty6 6 +/dev/tty7 7 +/dev/tty8 8 +/dev/ttyS0 9 +/dev/ttyS1 10 +/dev/ttyS2 11 +/dev/ttyS3 12 +/dev/ttyS4 13 +/dev/ttyS5 14 +/dev/ttyS6 15 +/dev/ttyS7 16 + \ No newline at end of file diff --git a/src/plugins/vbng/etc/radiusclient.conf b/src/plugins/vbng/etc/radiusclient.conf new file mode 100644 index 0000000..3a315b4 --- /dev/null +++ b/src/plugins/vbng/etc/radiusclient.conf @@ -0,0 +1,92 @@ +# General settings + +# specify which authentication comes first respectively which +# authentication is used. possible values are: "radius" and "local". +# if you specify "radius,local" then the RADIUS server is asked +# first then the local one. if only one keyword is specified only +# this server is asked. +auth_order radius,local + +# maximum login tries a user has +login_tries 4 + +# timeout for all login tries +# if this time is exceeded the user is kicked out +login_timeout 60 + +# name of the nologin file which when it exists disables logins. +# it may be extended by the ttyname which will result in +# a terminal specific lock (e.g. /etc/nologin.ttyS2 will disable +# logins on /dev/ttyS2) +nologin /etc/nologin + +# name of the issue file. it's only display when no username is passed +# on the radlogin command line +issue /usr/local/etc/radiusclient/issue + +# RADIUS settings + +# RADIUS server to use for authentication requests. this config +# item can appear more then one time. if multiple servers are +# defined they are tried in a round robin fashion if one +# server is not answering. +# optionally you can specify a the port number on which is remote +# RADIUS listens separated by a colon from the hostname. if +# no port is specified /etc/services is consulted of the radius +# service. if this fails also a compiled in default is used. +authserver localhost + +# RADIUS server to use for accouting requests. All that I +# said for authserver applies, too. +# +acctserver localhost + +# file holding shared secrets used for the communication +# between the RADIUS client and server +servers /usr/local/etc/radiusclient/servers + +# dictionary of allowed attributes and values +# just like in the normal RADIUS distributions +dictionary /usr/local/etc/radiusclient/dictionary + +# program to call for a RADIUS authenticated login +login_radius /usr/local/sbin/login.radius + +# file which holds sequence number for communication with the +# RADIUS server +seqfile /var/run/radius.seq + +# file which specifies mapping between ttyname and NAS-Port attribute +mapfile /usr/local/etc/radiusclient/port-id-map + +# default authentication realm to append to all usernames if no +# realm was explicitly specified by the user +# the radiusd directly form Livingston doesnt use any realms, so leave +# it blank then +default_realm + +# time to wait for a reply from the RADIUS server +radius_timeout 10 + +# resend request this many times before trying the next server +radius_retries 3 + +# The length of time in seconds that we skip a nonresponsive RADIUS +# server for transaction requests. Server(s) being in the "dead" state +# are tried only after all other non-dead servers have been tried and +# failed or timeouted. The deadtime interval starts when the server +# does not respond to an authentication/accounting request transmissions. +# When the interval expires, the "dead" server would be re-tried again, +# and if it's still down then it will be considered "dead" for another +# such interval and so on. This option is no-op if there is only one +# server in the list. Set to 0 in order to disable the feature. +radius_deadtime 0 + +# local address from which radius packets have to be sent +bindaddr * + +# LOCAL settings + +# program to execute for local login +# it must support the -f flag for preauthenticated login +login_local /bin/login diff --git a/src/plugins/vbng/etc/radiusclient.conf.in b/src/plugins/vbng/etc/radiusclient.conf.in new file mode 100644 index 0000000..fdf62e6 --- /dev/null +++ b/src/plugins/vbng/etc/radiusclient.conf.in @@ -0,0 +1,92 @@ +# General settings + +# specify which authentication comes first respectively which +# authentication is used. possible values are: "radius" and "local". +# if you specify "radius,local" then the RADIUS server is asked +# first then the local one. if only one keyword is specified only +# this server is asked. +auth_order radius,local + +# maximum login tries a user has +login_tries 4 + +# timeout for all login tries +# if this time is exceeded the user is kicked out +login_timeout 60 + +# name of the nologin file which when it exists disables logins. +# it may be extended by the ttyname which will result in +# a terminal specific lock (e.g. /etc/nologin.ttyS2 will disable +# logins on /dev/ttyS2) +nologin /etc/nologin + +# name of the issue file. it's only display when no username is passed +# on the radlogin command line +issue @pkgsysconfdir@/issue + +# RADIUS settings + +# RADIUS server to use for authentication requests. this config +# item can appear more then one time. if multiple servers are +# defined they are tried in a round robin fashion if one +# server is not answering. +# optionally you can specify a the port number on which is remote +# RADIUS listens separated by a colon from the hostname. if +# no port is specified /etc/services is consulted of the radius +# service. if this fails also a compiled in default is used. +authserver localhost + +# RADIUS server to use for accouting requests. All that I +# said for authserver applies, too. +# +acctserver localhost + +# file holding shared secrets used for the communication +# between the RADIUS client and server +servers @pkgsysconfdir@/servers + +# dictionary of allowed attributes and values +# just like in the normal RADIUS distributions +dictionary @pkgsysconfdir@/dictionary + +# program to call for a RADIUS authenticated login +login_radius @sbindir@/login.radius + +# file which holds sequence number for communication with the +# RADIUS server +seqfile /var/run/radius.seq + +# file which specifies mapping between ttyname and NAS-Port attribute +mapfile @pkgsysconfdir@/port-id-map + +# default authentication realm to append to all usernames if no +# realm was explicitly specified by the user +# the radiusd directly form Livingston doesnt use any realms, so leave +# it blank then +default_realm + +# time to wait for a reply from the RADIUS server +radius_timeout 10 + +# resend request this many times before trying the next server +radius_retries 3 + +# The length of time in seconds that we skip a nonresponsive RADIUS +# server for transaction requests. Server(s) being in the "dead" state +# are tried only after all other non-dead servers have been tried and +# failed or timeouted. The deadtime interval starts when the server +# does not respond to an authentication/accounting request transmissions. +# When the interval expires, the "dead" server would be re-tried again, +# and if it's still down then it will be considered "dead" for another +# such interval and so on. This option is no-op if there is only one +# server in the list. Set to 0 in order to disable the feature. +radius_deadtime 0 + +# local address from which radius packets have to be sent +bindaddr * + +# LOCAL settings + +# program to execute for local login +# it must support the -f flag for preauthenticated login +login_local /bin/login diff --git a/src/plugins/vbng/etc/servers b/src/plugins/vbng/etc/servers new file mode 100644 index 0000000..50eddd3 --- /dev/null +++ b/src/plugins/vbng/etc/servers @@ -0,0 +1,10 @@ +## Server Name or Client/Server pair Key +## ---------------- --------------- +# +#portmaster.elemental.net hardlyasecret +#portmaster2.elemental.net donttellanyone +# +## uncomment the following line for simple testing of radlogin +## with freeradius-server +# +#localhost/localhost testing123 diff --git a/src/plugins/vbng/include/freeradius-client.h b/src/plugins/vbng/include/freeradius-client.h new file mode 100644 index 0000000..96c7546 --- /dev/null +++ b/src/plugins/vbng/include/freeradius-client.h @@ -0,0 +1,528 @@ +/* + * $Id: freeradius-client.h,v 1.18 2010/06/15 09:22:51 aland Exp $ + * + * Copyright (C) 1995,1996,1997,1998 Lars Fenneberg + * + * Copyright 1992 Livingston Enterprises, Inc. + * + * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan + * and Merit Network, Inc. All Rights Reserved + * + * See the file COPYRIGHT for the respective terms and conditions. + * If the file is missing contact me at lf@elemental.net + * and I'll send you a copy. + * + */ + +#ifndef FREERADIUS_CLIENT_H +#define FREERADIUS_CLIENT_H + +#ifdef CP_DEBUG +#define DEBUG(args, ...) rc_log(## args) +#else +#define DEBUG(args, ...) ; +#endif + +#include +/* + * Include for C99 uintX_t defines is stdint.h on most systems. Solaris uses + * inttypes.h instead. Comment out the stdint include if you get an error, + * and uncomment the inttypes.h include. + */ +#include +/* #include */ +#include +#include + +#undef __BEGIN_DECLS +#undef __END_DECLS +#ifdef __cplusplus +# define __BEGIN_DECLS extern "C" { +# define __END_DECLS } +#else +# define __BEGIN_DECLS /* empty */ +# define __END_DECLS /* empty */ +#endif + +#define AUTH_VECTOR_LEN 16 +#define AUTH_PASS_LEN (3 * 16) /* multiple of 16 */ +#define AUTH_ID_LEN 64 +#define AUTH_STRING_LEN 253 /* maximum of 253 */ + +#define BUFFER_LEN 8192 + +#define NAME_LENGTH 32 +#define GETSTR_LENGTH 128 /* must be bigger than AUTH_PASS_LEN */ + +#define MAX_SECRET_LENGTH (3 * 16) /* MUST be multiple of 16 */ + +#define VENDOR(x) (((x) >> 16) & 0xffff) +#define ATTRID(x) ((x) & 0xffff) + +#define PW_MAX_MSG_SIZE 4096 + +/* codes for radius_buildreq, radius_getport, etc. */ +#define AUTH 0 +#define ACCT 1 + +/* defines for config.c */ + +#define SERVER_MAX 8 + +#define AUTH_LOCAL_FST (1<<0) +#define AUTH_RADIUS_FST (1<<1) +#define AUTH_LOCAL_SND (1<<2) +#define AUTH_RADIUS_SND (1<<3) + +typedef struct server { + int max; + char *name[SERVER_MAX]; + uint16_t port[SERVER_MAX]; + char *secret[SERVER_MAX]; + double deadtime_ends[SERVER_MAX]; +} SERVER; + +typedef struct pw_auth_hdr +{ + uint8_t code; + uint8_t id; + uint16_t length; + uint8_t vector[AUTH_VECTOR_LEN]; + uint8_t data[2]; +} AUTH_HDR; + +struct rc_conf +{ + struct _option *config_options; + uint32_t this_host_ipaddr; + uint32_t *this_host_bind_ipaddr; + struct map2id_s *map2id_list; + struct dict_attr *dictionary_attributes; + struct dict_value *dictionary_values; + struct dict_vendor *dictionary_vendors; + char buf[GETSTR_LENGTH]; + char buf1[14]; + char ifname[512]; +}; + +typedef struct rc_conf rc_handle; + +#define AUTH_HDR_LEN 20 +#define CHAP_VALUE_LENGTH 16 + +#define PW_AUTH_UDP_PORT 1645 +#define PW_ACCT_UDP_PORT 1646 + +#define PW_TYPE_STRING 0 +#define PW_TYPE_INTEGER 1 +#define PW_TYPE_IPADDR 2 +#define PW_TYPE_DATE 3 +#define PW_TYPE_IPV6ADDR 4 +#define PW_TYPE_IPV6PREFIX 5 + +/* standard RADIUS codes */ + +#define PW_ACCESS_REQUEST 1 +#define PW_ACCESS_ACCEPT 2 +#define PW_ACCESS_REJECT 3 +#define PW_ACCOUNTING_REQUEST 4 +#define PW_ACCOUNTING_RESPONSE 5 +#define PW_ACCOUNTING_STATUS 6 +#define PW_PASSWORD_REQUEST 7 +#define PW_PASSWORD_ACK 8 +#define PW_PASSWORD_REJECT 9 +#define PW_ACCOUNTING_MESSAGE 10 +#define PW_ACCESS_CHALLENGE 11 +#define PW_STATUS_SERVER 12 +#define PW_STATUS_CLIENT 13 + + +/* standard RADIUS attribute-value pairs */ + +#define PW_USER_NAME 1 /* string */ +#define PW_USER_PASSWORD 2 /* string */ +#define PW_CHAP_PASSWORD 3 /* string */ +#define PW_NAS_IP_ADDRESS 4 /* ipaddr */ +#define PW_NAS_PORT 5 /* integer */ +#define PW_SERVICE_TYPE 6 /* integer */ +#define PW_FRAMED_PROTOCOL 7 /* integer */ +#define PW_FRAMED_IP_ADDRESS 8 /* ipaddr */ +#define PW_FRAMED_IP_NETMASK 9 /* ipaddr */ +#define PW_FRAMED_ROUTING 10 /* integer */ +#define PW_FILTER_ID 11 /* string */ +#define PW_FRAMED_MTU 12 /* integer */ +#define PW_FRAMED_COMPRESSION 13 /* integer */ +#define PW_LOGIN_IP_HOST 14 /* ipaddr */ +#define PW_LOGIN_SERVICE 15 /* integer */ +#define PW_LOGIN_PORT 16 /* integer */ +#define PW_OLD_PASSWORD 17 /* string */ /* deprecated */ +#define PW_REPLY_MESSAGE 18 /* string */ +#define PW_LOGIN_CALLBACK_NUMBER 19 /* string */ +#define PW_FRAMED_CALLBACK_ID 20 /* string */ +#define PW_EXPIRATION 21 /* date */ /* deprecated */ +#define PW_FRAMED_ROUTE 22 /* string */ +#define PW_FRAMED_IPX_NETWORK 23 /* integer */ +#define PW_STATE 24 /* string */ +#define PW_CLASS 25 /* string */ +#define PW_VENDOR_SPECIFIC 26 /* string */ +#define PW_SESSION_TIMEOUT 27 /* integer */ +#define PW_IDLE_TIMEOUT 28 /* integer */ +#define PW_TERMINATION_ACTION 29 /* integer */ +#define PW_CALLED_STATION_ID 30 /* string */ +#define PW_CALLING_STATION_ID 31 /* string */ +#define PW_NAS_IDENTIFIER 32 /* string */ +#define PW_PROXY_STATE 33 /* string */ +#define PW_LOGIN_LAT_SERVICE 34 /* string */ +#define PW_LOGIN_LAT_NODE 35 /* string */ +#define PW_LOGIN_LAT_GROUP 36 /* string */ +#define PW_FRAMED_APPLETALK_LINK 37 /* integer */ +#define PW_FRAMED_APPLETALK_NETWORK 38 /* integer */ +#define PW_FRAMED_APPLETALK_ZONE 39 /* string */ +#define PW_EVENT_TIMESTAMP 55 /* integer */ +#define PW_CHAP_CHALLENGE 60 /* string */ +#define PW_NAS_PORT_TYPE 61 /* integer */ +#define PW_PORT_LIMIT 62 /* integer */ +#define PW_LOGIN_LAT_PORT 63 /* string */ +#define PW_CONNECT_INFO 77 /* string */ +#define PW_MESSAGE_AUTHENTICATOR 80 /* string */ + +/* RFC3162 IPv6 attributes */ + +#define PW_NAS_IPV6_ADDRESS 95 /* string */ +#define PW_FRAMED_INTERFACE_ID 96 /* string */ +#define PW_FRAMED_IPV6_PREFIX 97 /* string */ +#define PW_LOGIN_IPV6_HOST 98 /* string */ +#define PW_FRAMED_IPV6_ROUTE 99 /* string */ +#define PW_FRAMED_IPV6_POOL 100 /* string */ + +/* RFC6911 IPv6 attributes */ +#define PW_FRAMED_IPV6_ADDRESS 168 /* ipaddr6 */ +#define PW_DNS_SERVER_IPV6_ADDRESS 169 /* ipaddr6 */ +#define PW_ROUTE_IPV6_INFORMATION 170 /* ipv6prefix */ + +/* Accounting */ + +#define PW_ACCT_STATUS_TYPE 40 /* integer */ +#define PW_ACCT_DELAY_TIME 41 /* integer */ +#define PW_ACCT_INPUT_OCTETS 42 /* integer */ +#define PW_ACCT_OUTPUT_OCTETS 43 /* integer */ +#define PW_ACCT_SESSION_ID 44 /* string */ +#define PW_ACCT_AUTHENTIC 45 /* integer */ +#define PW_ACCT_SESSION_TIME 46 /* integer */ +#define PW_ACCT_INPUT_PACKETS 47 /* integer */ +#define PW_ACCT_OUTPUT_PACKETS 48 /* integer */ +#define PW_ACCT_TERMINATE_CAUSE 49 /* integer */ +#define PW_ACCT_MULTI_SESSION_ID 50 /* string */ +#define PW_ACCT_LINK_COUNT 51 /* integer */ +#define PW_ACCT_INPUT_GIGAWORDS 52 /* integer */ +#define PW_ACCT_OUTPUT_GIGAWORDS 53 /* integer */ + +/* Experimental SIP-specific attributes (draft-sterman-aaa-sip-00.txt etc) */ + +#define PW_DIGEST_RESPONSE 206 /* string */ +#define PW_DIGEST_ATTRIBUTES 207 /* string */ +#define PW_DIGEST_REALM 1063 /* string */ +#define PW_DIGEST_NONCE 1064 /* string */ +#define PW_DIGEST_METHOD 1065 /* string */ +#define PW_DIGEST_URI 1066 /* string */ +#define PW_DIGEST_QOP 1067 /* string */ +#define PW_DIGEST_ALGORITHM 1068 /* string */ +#define PW_DIGEST_BODY_DIGEST 1069 /* string */ +#define PW_DIGEST_CNONCE 1070 /* string */ +#define PW_DIGEST_NONCE_COUNT 1071 /* string */ +#define PW_DIGEST_USER_NAME 1072 /* string */ + +/* Merit Experimental Extensions */ + +#define PW_USER_ID 222 /* string */ +#define PW_USER_REALM 223 /* string */ + +/* Integer Translations */ + +/* SERVICE TYPES */ + +#define PW_LOGIN 1 +#define PW_FRAMED 2 +#define PW_CALLBACK_LOGIN 3 +#define PW_CALLBACK_FRAMED 4 +#define PW_OUTBOUND 5 +#define PW_ADMINISTRATIVE 6 +#define PW_NAS_PROMPT 7 +#define PW_AUTHENTICATE_ONLY 8 +#define PW_CALLBACK_NAS_PROMPT 9 + +/* FRAMED PROTOCOLS */ + +#define PW_PPP 1 +#define PW_SLIP 2 +#define PW_ARA 3 +#define PW_GANDALF 4 +#define PW_XYLOGICS 5 + +/* FRAMED ROUTING VALUES */ + +#define PW_NONE 0 +#define PW_BROADCAST 1 +#define PW_LISTEN 2 +#define PW_BROADCAST_LISTEN 3 + +/* FRAMED COMPRESSION TYPES */ + +#define PW_VAN_JACOBSON_TCP_IP 1 +#define PW_IPX_HEADER_COMPRESSION 2 + +/* LOGIN SERVICES */ + +#define PW_TELNET 0 +#define PW_RLOGIN 1 +#define PW_TCP_CLEAR 2 +#define PW_PORTMASTER 3 +#define PW_LAT 4 +#define PW_X25_PAD 5 +#define PW_X25_T3POS 6 + +/* TERMINATION ACTIONS */ + +#define PW_DEFAULT 0 +#define PW_RADIUS_REQUEST 1 + +/* PROHIBIT PROTOCOL */ + +#define PW_DUMB 0 /* 1 and 2 are defined in FRAMED PROTOCOLS */ +#define PW_AUTH_ONLY 3 +#define PW_ALL 255 + +/* ACCOUNTING STATUS TYPES */ + +#define PW_STATUS_START 1 +#define PW_STATUS_STOP 2 +#define PW_STATUS_ALIVE 3 +#define PW_STATUS_MODEM_START 4 +#define PW_STATUS_MODEM_STOP 5 +#define PW_STATUS_CANCEL 6 +#define PW_ACCOUNTING_ON 7 +#define PW_ACCOUNTING_OFF 8 + +/* ACCOUNTING TERMINATION CAUSES */ + +#define PW_USER_REQUEST 1 +#define PW_LOST_CARRIER 2 +#define PW_LOST_SERVICE 3 +#define PW_ACCT_IDLE_TIMEOUT 4 +#define PW_ACCT_SESSION_TIMEOUT 5 +#define PW_ADMIN_RESET 6 +#define PW_ADMIN_REBOOT 7 +#define PW_PORT_ERROR 8 +#define PW_NAS_ERROR 9 +#define PW_NAS_REQUEST 10 +#define PW_NAS_REBOOT 11 +#define PW_PORT_UNNEEDED 12 +#define PW_PORT_PREEMPTED 13 +#define PW_PORT_SUSPENDED 14 +#define PW_SERVICE_UNAVAILABLE 15 +#define PW_CALLBACK 16 +#define PW_USER_ERROR 17 +#define PW_HOST_REQUEST 18 + +/* NAS PORT TYPES */ + +#define PW_ASYNC 0 +#define PW_SYNC 1 +#define PW_ISDN_SYNC 2 +#define PW_ISDN_SYNC_V120 3 +#define PW_ISDN_SYNC_V110 4 +#define PW_VIRTUAL 5 + +/* AUTHENTIC TYPES */ +#define PW_RADIUS 1 +#define PW_LOCAL 2 +#define PW_REMOTE 3 + +/* Server data structures */ + +typedef struct dict_attr +{ + char name[NAME_LENGTH + 1]; /* attribute name */ + int value; /* attribute index */ + int type; /* string, int, etc. */ + struct dict_attr *next; +} DICT_ATTR; + +typedef struct dict_value +{ + char attrname[NAME_LENGTH +1]; + char name[NAME_LENGTH + 1]; + int value; + struct dict_value *next; +} DICT_VALUE; + +typedef struct dict_vendor +{ + char vendorname[NAME_LENGTH +1]; + int vendorpec; + struct dict_vendor *next; +} DICT_VENDOR; + +typedef struct value_pair +{ + char name[NAME_LENGTH + 1]; + int attribute; + int type; + uint32_t lvalue; + char strvalue[AUTH_STRING_LEN + 1]; + struct value_pair *next; +} VALUE_PAIR; + +/* don't change this, as it has to be the same as in the Merit radiusd code */ +#define MGMT_POLL_SECRET "Hardlyasecret" + +/* Define return codes from "SendServer" utility */ + +#define BADRESP_RC -2 +#define ERROR_RC -1 +#define OK_RC 0 +#define TIMEOUT_RC 1 +#define REJECT_RC 2 + +typedef struct send_data /* Used to pass information to sendserver() function */ +{ + uint8_t code; /* RADIUS packet code */ + uint8_t seq_nbr; /* Packet sequence number */ + char *server; /* Name/addrress of RADIUS server */ + int svc_port; /* RADIUS protocol destination port */ + char *secret; /* Shared secret of RADIUS server */ + int timeout; /* Session timeout in seconds */ + int retries; + VALUE_PAIR *send_pairs; /* More a/v pairs to send */ + VALUE_PAIR *receive_pairs; /* Where to place received a/v pairs */ +} SEND_DATA; + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + +typedef struct env +{ + int maxsize, size; + char **env; +} ENV; + +#define ENV_SIZE 128 + +__BEGIN_DECLS + +/* Function prototypes */ + +/* avpair.c */ + +VALUE_PAIR *rc_avpair_add(rc_handle const *, VALUE_PAIR **, int, void const *, int, int); +int rc_avpair_assign(VALUE_PAIR *, void const *, int); +VALUE_PAIR *rc_avpair_new(rc_handle const *, int, void const *, int, int); +VALUE_PAIR *rc_avpair_gen(rc_handle const *, VALUE_PAIR *, unsigned char const *, int, int); +VALUE_PAIR *rc_avpair_get(VALUE_PAIR *, int, int); +void rc_avpair_insert(VALUE_PAIR **, VALUE_PAIR *, VALUE_PAIR *); +void rc_avpair_free(VALUE_PAIR *); +int rc_avpair_parse(rc_handle const *, char const *, VALUE_PAIR **); +int rc_avpair_tostr(rc_handle const *, VALUE_PAIR *, char *, int, char *, int); +char *rc_avpair_log(rc_handle const *, VALUE_PAIR *, char *buf, size_t buf_len); +VALUE_PAIR *rc_avpair_readin(rc_handle const *, FILE *); + +/* buildreq.c */ + +void rc_buildreq(rc_handle const *, SEND_DATA *, int, char *, unsigned short, char *, int, int); +unsigned char rc_get_id(); +int rc_auth(rc_handle *, uint32_t, VALUE_PAIR *, VALUE_PAIR **, char *); +int rc_auth_proxy(rc_handle *, VALUE_PAIR *, VALUE_PAIR **, char *); +int rc_acct(rc_handle *, uint32_t, VALUE_PAIR *); +int rc_acct_proxy(rc_handle *, VALUE_PAIR *); +int rc_check(rc_handle *, char *, char *, unsigned short, char *); + +int rc_aaa(rc_handle *rh, uint32_t client_port, VALUE_PAIR *send, VALUE_PAIR **received, + char *msg, int add_nas_port, int request_type); + +/* clientid.c */ + +int rc_read_mapfile(rc_handle *, char const *); +uint32_t rc_map2id(rc_handle const *, char const *); +void rc_map2id_free(rc_handle *); + +/* config.c */ + +rc_handle *rc_read_config(char const *); +char *rc_conf_str(rc_handle const *, char const *); +int rc_conf_int(rc_handle const *, char const *); +SERVER *rc_conf_srv(rc_handle const *, char const *); +int rc_find_server(rc_handle const *, char const *, uint32_t *, char *); +void rc_config_free(rc_handle *); +int rc_add_config(rc_handle *, char const *, char const *, char const *, int); +rc_handle *rc_config_init(rc_handle *); +int test_config(rc_handle const *, char const *); + +/* dict.c */ + +int rc_read_dictionary(rc_handle *, char const *); +DICT_ATTR *rc_dict_getattr(rc_handle const *, int); +DICT_ATTR *rc_dict_findattr(rc_handle const *, char const *); +DICT_VALUE *rc_dict_findval(rc_handle const *, char const *); +DICT_VENDOR *rc_dict_findvend(rc_handle const *, char const *); +DICT_VENDOR *rc_dict_getvend(rc_handle const *, int); +DICT_VALUE * rc_dict_getval(rc_handle const *, uint32_t, char const *); +void rc_dict_free(rc_handle *); + +/* ip_util.c */ + +struct hostent *rc_gethostbyname(char const *); +struct hostent *rc_gethostbyaddr(char const *, size_t, int); +uint32_t rc_get_ipaddr(char const *); +int rc_good_ipaddr(char const *); +char const *rc_ip_hostname(uint32_t); +unsigned short rc_getport(int); +int rc_own_hostname(char *, int); +uint32_t rc_own_ipaddress(rc_handle *); +uint32_t rc_own_bind_ipaddress(rc_handle *); +struct sockaddr; +int rc_get_srcaddr(struct sockaddr *, struct sockaddr *); + + +/* log.c */ + +void rc_openlog(char const *); +void rc_log(int, char const *, ...); + +/* sendserver.c */ + +int rc_send_server(rc_handle *, SEND_DATA *, char *); + +/* util.c */ + +void rc_str2tm(char const *, struct tm *); +char *rc_getifname(rc_handle *, char const *); +char *rc_getstr(rc_handle *, char const *, int); +void rc_mdelay(int); +char *rc_mksid(rc_handle *); +rc_handle *rc_new(void); +void rc_destroy(rc_handle *); +char *rc_fgetln(FILE *, size_t *); +double rc_getctime(void); + +/* env.c */ + +struct env *rc_new_env(int); +void rc_free_env(struct env *); +int rc_add_env(struct env *, char const *, char const *); +int rc_import_env(struct env *, char const **); + +/* md5.c */ + +void rc_md5_calc(unsigned char *, unsigned char const *, unsigned int); + +__END_DECLS + +#endif /* FREERADIUS_CLIENT_H */ diff --git a/src/plugins/vbng/include/includes.h b/src/plugins/vbng/include/includes.h new file mode 100644 index 0000000..908f0e7 --- /dev/null +++ b/src/plugins/vbng/include/includes.h @@ -0,0 +1,182 @@ +/* + * $Id: includes.h,v 1.6 2007/06/21 18:07:22 cparker Exp $ + * + * Copyright (C) 1997 Lars Fenneberg + * + * Copyright 1992 Livingston Enterprises, Inc. + * + * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan + * and Merit Network, Inc. All Rights Reserved + * + * See the file COPYRIGHT for the respective terms and conditions. + * If the file is missing contact me at lf@elemental.net + * and I'll send you a copy. + * + */ + +#include "config.h" + +/* AIX requires this to be the first thing in the file. */ +#ifndef __GNUC__ +# if HAVE_ALLOCA_H +# include +# else +# ifdef _AIX +# pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ + char *alloca (); +# endif +# endif +# endif +#endif + +#include + +#include +#include +#include + +#ifdef HAVE_NETDB_H +#include +#endif + +#ifdef HAVE_SYSLOG_H +#include +#endif + +#ifdef STDC_HEADERS +# include +# include +# include +#else +# include +# ifndef HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +#endif + +/* I realize that this is ugly and unsafe.. :( */ +#ifndef HAVE_SNPRINTF +# define snprintf(buf, len, format, ...) sprintf(buf, format, __VA_ARGS__) +#endif +#ifndef HAVE_VSNPRINTF +# define vsnprintf(buf, len, format, ap) vsprintf(buf, format, ap) +#endif + +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ + +#ifdef HAVE_FCNTL_H +# include +#endif + +#ifdef HAVE_SYS_FCNTL_H +# include +#endif + +#ifdef HAVE_SYS_FILE_H +# include +#endif + +#ifdef HAVE_SYS_STAT_H +# include +#endif + +#ifdef HAVE_SYS_UTSNAME_H +# include +#endif + +#ifdef HAVE_SYS_IOCTL_H +# include +#endif + +#ifdef HAVE_CRYPT_H +# include +#endif + +#ifdef HAVE_LIMITS_H +# include +#endif + +#ifdef HAVE_TERMIOS_H +# include +#endif + +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + +#ifndef UCHAR_MAX +# ifdef __STDC__ +# define UCHAR_MAX 255U +# else +# define UCHAR_MAX 255 +# endif +#endif + +#ifdef HAVE_PWD_H +#include +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#if defined(HAVE_SIGNAL_H) +# include +#endif +#if defined(HAVE_SYS_SIGNAL_H) +# include +#endif + +#ifdef NEED_SIG_PROTOTYPES +int sigemptyset(sigset_t *); +int sigaddset(sigset_t *, int); +int sigprocmask (int, sigset_t *, sigset_t *); +#endif + +#if HAVE_GETOPT_H +# include +#endif + +#if defined(HAVE_SHADOW_H) && defined(HAVE_SHADOW_PASSWORDS) +# include +#endif + +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +/* + * prefer srandom/random over srand/rand as there generator has a + * better distribution of the numbers on certain systems. + * on Linux both generators are identical. + */ +#ifndef HAVE_RANDOM +# ifdef HAVE_RAND +# define srandom srand +# define random rand +# endif +#endif + +/* rlib/lock.c */ +int do_lock_exclusive(FILE *); +int do_unlock(FILE *); diff --git a/src/plugins/vbng/include/messages.h b/src/plugins/vbng/include/messages.h new file mode 100644 index 0000000..9a5f0e8 --- /dev/null +++ b/src/plugins/vbng/include/messages.h @@ -0,0 +1,53 @@ +/* + * $Id: messages.h,v 1.2 2004/02/23 20:10:39 sobomax Exp $ + * + * Copyright (C) 1995,1996 Lars Fenneberg + * + * Copyright 1992 Livingston Enterprises, Inc. + * + * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan + * and Merit Network, Inc. All Rights Reserved + * + * See the file COPYRIGHT for the respective terms and conditions. + * If the file is missing contact me at lf@elemental.net + * and I'll send you a copy. + * + */ + +/* + * Only messages that the user gets under normal use are in here. + * Error messages and such are still in the source code. + */ + +#ifndef MESSAGES_H +#define MESSAGES_H + +/* radlogin.c */ + +#define SC_LOGIN "login: " +#define SC_PASSWORD "Password: " + +#define SC_TIMEOUT "\r\nlogin timed out after %d seconds. Bye.\r\n" +#define SC_EXCEEDED "Maximum login tries exceeded. Go away!\r\n" + +#define SC_RADIUS_OK "RADIUS: Authentication OK\r\n" +#define SC_RADIUS_FAILED "RADIUS: Authentication failure\r\n" + +#define SC_LOCAL_OK "local: Authentication OK\r\n" +#define SC_LOCAL_FAILED "local: Authentication failure\r\n" +#define SC_NOLOGIN "\r\nSystem closed for maintenance. Try again later...\r\n" + +#define SC_SERVER_REPLY "RADIUS: %s" + +#define SC_DEFAULT_ISSUE "(\\I)\r\n\r\n\\S \\R (\\N) (port \\L)\r\n\r\n" + +/* radacct.c */ + +#define SC_ACCT_OK "RADIUS accounting OK\r\n" +#define SC_ACCT_FAILED "RADIUS accounting failed (RC=%i)\r\n" + +/* radstatus.c */ + +#define SC_STATUS_FAILED "RADIUS: Status failure\r\n" + +#endif /* MESSAGES_H */ diff --git a/src/plugins/vbng/include/pathnames.h b/src/plugins/vbng/include/pathnames.h new file mode 100644 index 0000000..0256d47 --- /dev/null +++ b/src/plugins/vbng/include/pathnames.h @@ -0,0 +1,28 @@ +/* + * $Id: pathnames.h,v 1.2 2004/02/23 20:10:39 sobomax Exp $ + * + * Copyright (C) 1995,1996 Lars Fenneberg + * + * Copyright 1992 Livingston Enterprises, Inc. + * + * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan + * and Merit Network, Inc. All Rights Reserved + * + * See the file COPYRIGHT for the respective terms and conditions. + * If the file is missing contact me at lf@elemental.net + * and I'll send you a copy. + * + */ + +#ifndef PATHNAMES_H +#define PATHNAMES_H + +#define _PATH_DEV_URANDOM "/dev/urandom" /* Linux only */ +#define _PATH_ETC_ISSUE "/etc/issue" + +/* normally defined in the Makefile */ +#ifndef _PATH_ETC_RADIUSCLIENT_CONF +#define _PATH_ETC_RADIUSCLIENT_CONF "/etc/radiusclient.conf" +#endif + +#endif /* PATHNAMES_H */ diff --git a/src/plugins/vbng/lib/avpair.c b/src/plugins/vbng/lib/avpair.c new file mode 100644 index 0000000..8ce2a8e --- /dev/null +++ b/src/plugins/vbng/lib/avpair.c @@ -0,0 +1,874 @@ +/* + * $Id: avpair.c,v 1.26 2010/06/15 09:22:52 aland Exp $ + * + * Copyright (C) 1995 Lars Fenneberg + * + * Copyright 1992 Livingston Enterprises, Inc. + * + * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan + * and Merit Network, Inc. All Rights Reserved + * + * See the file COPYRIGHT for the respective terms and conditions. + * If the file is missing contact me at lf@elemental.net + * and I'll send you a copy. + * + */ + +#include +#include +#include + +/* + * Function: rc_avpair_add + * + * Purpose: add an attribute-value pair to the given list. + * + * Returns: pointer to added a/v pair upon success, NULL pointer upon failure. + * + * Remarks: Always appends the new pair to the end of the list. + * + */ + +VALUE_PAIR *rc_avpair_add (rc_handle const *rh, VALUE_PAIR **list, int attrid, void const *pval, int len, int vendorpec) +{ + VALUE_PAIR *vp; + + vp = rc_avpair_new (rh, attrid, pval, len, vendorpec); + + if (vp != NULL) + { + rc_avpair_insert (list, NULL, vp); + } + + return vp; + +} + +/* + * Function: rc_avpair_assign + * + * Purpose: assign the given value to an attribute-value pair. + * + * Returns: 0 on success, + * -1 on failure. + * + */ + +int rc_avpair_assign (VALUE_PAIR *vp, void const *pval, int len) +{ + + switch (vp->type) + { + case PW_TYPE_STRING: + if (len == -1) + len = (uint32_t)strlen((char const *)pval); + if (len > AUTH_STRING_LEN) { + rc_log(LOG_ERR, "rc_avpair_assign: bad attribute length"); + return -1; + } + memcpy(vp->strvalue, (char const *)pval, len); + vp->strvalue[len] = '\0'; + vp->lvalue = len; + break; + + case PW_TYPE_DATE: + case PW_TYPE_INTEGER: + case PW_TYPE_IPADDR: + vp->lvalue = * (uint32_t *) pval; + break; + case PW_TYPE_IPV6ADDR: + if (len != 16) { + rc_log(LOG_ERR, "rc_avpair_assign: bad IPv6 length"); + return -1; + } + memcpy(vp->strvalue, (char const *)pval, len); + vp->lvalue = len; + break; + + case PW_TYPE_IPV6PREFIX: + if (len < 2 || len > 18) { + rc_log(LOG_ERR, "rc_avpair_assign: bad IPv6 prefix length"); + return -1; + } + memcpy(vp->strvalue, (char const *)pval, len); + vp->lvalue = len; + break; + + default: + rc_log(LOG_ERR, "rc_avpair_assign: unknown attribute %d", vp->type); + return -1; + } + return 0; +} + +/* + * Function: rc_avpair_new + * + * Purpose: make a new attribute-value pair with given parameters. + * + * Returns: pointer to generated a/v pair when successful, NULL when failure. + * + */ + +VALUE_PAIR *rc_avpair_new (rc_handle const *rh, int attrid, void const *pval, int len, int vendorpec) +{ + VALUE_PAIR *vp = NULL; + DICT_ATTR *pda; + + attrid = attrid | (vendorpec << 16); + if ((pda = rc_dict_getattr (rh, attrid)) == NULL) + { + rc_log(LOG_ERR,"rc_avpair_new: unknown attribute %d", attrid); + return NULL; + } + if (vendorpec != 0 && rc_dict_getvend(rh, vendorpec) == NULL) + { + rc_log(LOG_ERR,"rc_avpair_new: unknown Vendor-Id %d", vendorpec); + return NULL; + } + if ((vp = malloc (sizeof (VALUE_PAIR))) != NULL) + { + strncpy (vp->name, pda->name, sizeof (vp->name)); + vp->attribute = attrid; + vp->next = NULL; + vp->type = pda->type; + if (rc_avpair_assign (vp, pval, len) == 0) + { + /* XXX: Fix up Digest-Attributes */ + switch (vp->attribute) { + case PW_DIGEST_REALM: + case PW_DIGEST_NONCE: + case PW_DIGEST_METHOD: + case PW_DIGEST_URI: + case PW_DIGEST_QOP: + case PW_DIGEST_ALGORITHM: + case PW_DIGEST_BODY_DIGEST: + case PW_DIGEST_CNONCE: + case PW_DIGEST_NONCE_COUNT: + case PW_DIGEST_USER_NAME: + /* overlapping! */ + if (vp->lvalue > AUTH_STRING_LEN - 2) + vp->lvalue = AUTH_STRING_LEN - 2; + memmove(&vp->strvalue[2], &vp->strvalue[0], vp->lvalue); + vp->strvalue[0] = vp->attribute - PW_DIGEST_REALM + 1; + vp->lvalue += 2; + vp->strvalue[1] = vp->lvalue; + vp->strvalue[vp->lvalue] = '\0'; + vp->attribute = PW_DIGEST_ATTRIBUTES; + default: + break; + } + return vp; + } + free (vp); + vp = NULL; + } + else + { + rc_log(LOG_CRIT,"rc_avpair_new: out of memory"); + } + + return vp; +} + +/* + * + * Function: rc_avpair_gen + * + * Purpose: takes attribute/value pairs from buffer and builds a + * value_pair list using allocated memory. Uses recursion. + * + * Returns: value_pair list or NULL on failure + */ + +VALUE_PAIR * +rc_avpair_gen(rc_handle const *rh, VALUE_PAIR *pair, unsigned char const *ptr, + int length, int vendorpec) +{ + int attribute, attrlen, x_len; + unsigned char const *x_ptr; + uint32_t lvalue; + DICT_ATTR *attr; + VALUE_PAIR *rpair; + char buffer[(AUTH_STRING_LEN * 2) + 1]; + /* For hex string conversion. */ + char hex[3]; + + if (length < 2) { + rc_log(LOG_ERR, "rc_avpair_gen: received attribute with " + "invalid length"); + goto shithappens; + } + attrlen = ptr[1]; + if (length < attrlen || attrlen < 2) { + rc_log(LOG_ERR, "rc_avpair_gen: received attribute with " + "invalid length"); + goto shithappens; + } + + /* Advance to the next attribute and process recursively */ + if (length != attrlen) { + pair = rc_avpair_gen(rh, pair, ptr + attrlen, length - attrlen, + vendorpec); + if (pair == NULL) + return NULL; + } + + /* Actual processing */ + attribute = ptr[0] | (vendorpec << 16); + ptr += 2; + attrlen -= 2; + + /* VSA */ + if (attribute == PW_VENDOR_SPECIFIC) { + if (attrlen < 4) { + rc_log(LOG_ERR, "rc_avpair_gen: received VSA " + "attribute with invalid length"); + goto shithappens; + } + memcpy(&lvalue, ptr, 4); + vendorpec = ntohl(lvalue); + if (rc_dict_getvend(rh, vendorpec) == NULL) { + /* Warn and skip over the unknown VSA */ + rc_log(LOG_WARNING, "rc_avpair_gen: received VSA " + "attribute with unknown Vendor-Id %d", vendorpec); + return pair; + } + /* Process recursively */ + return rc_avpair_gen(rh, pair, ptr + 4, attrlen - 4, + vendorpec); + } + + /* Normal */ + attr = rc_dict_getattr(rh, attribute); + if (attr == NULL) { + buffer[0] = '\0'; /* Initial length. */ + x_ptr = ptr; + for (x_len = attrlen; x_len > 0; x_len--, x_ptr++) { + snprintf(hex, sizeof(hex), "%2.2X", x_ptr[0]); + strcat(buffer, hex); + } + if (vendorpec == 0) { + rc_log(LOG_WARNING, "rc_avpair_gen: received " + "unknown attribute %d of length %d: 0x%s", + attribute, attrlen + 2, buffer); + } else { + rc_log(LOG_WARNING, "rc_avpair_gen: received " + "unknown VSA attribute %d, vendor %d of " + "length %d: 0x%s", attribute & 0xffff, + VENDOR(attribute), attrlen + 2, buffer); + } + goto shithappens; + } + + rpair = malloc(sizeof(*rpair)); + if (rpair == NULL) { + rc_log(LOG_CRIT, "rc_avpair_gen: out of memory"); + goto shithappens; + } + memset(rpair, '\0', sizeof(*rpair)); + + /* Insert this new pair at the beginning of the list */ + rpair->next = pair; + pair = rpair; + strcpy(pair->name, attr->name); + pair->attribute = attr->value; + pair->type = attr->type; + + switch (attr->type) { + case PW_TYPE_STRING: + memcpy(pair->strvalue, (char *)ptr, (size_t)attrlen); + pair->strvalue[attrlen] = '\0'; + pair->lvalue = attrlen; + break; + + case PW_TYPE_INTEGER: + if (attrlen != 4) { + rc_log(LOG_ERR, "rc_avpair_gen: received INT " + "attribute with invalid length"); + goto shithappens; + } + case PW_TYPE_IPADDR: + if (attrlen != 4) { + rc_log(LOG_ERR, "rc_avpair_gen: received IPADDR" + " attribute with invalid length"); + goto shithappens; + } + memcpy((char *)&lvalue, (char *)ptr, 4); + pair->lvalue = ntohl(lvalue); + break; + case PW_TYPE_IPV6ADDR: + if (attrlen != 16) { + rc_log(LOG_ERR, "rc_avpair_gen: received IPV6ADDR" + " attribute with invalid length"); + goto shithappens; + } + memcpy(pair->strvalue, (char *)ptr, 16); + pair->lvalue = attrlen; + break; + case PW_TYPE_IPV6PREFIX: + if (attrlen > 18 || attrlen < 2) { + rc_log(LOG_ERR, "rc_avpair_gen: received IPV6PREFIX" + " attribute with invalid length: %d", attrlen); + goto shithappens; + } + memcpy(pair->strvalue, (char *)ptr, attrlen); + pair->lvalue = attrlen; + break; + case PW_TYPE_DATE: + if (attrlen != 4) { + rc_log(LOG_ERR, "rc_avpair_gen: received DATE " + "attribute with invalid length"); + goto shithappens; + } + + default: + rc_log(LOG_WARNING, "rc_avpair_gen: %s has unknown type", + attr->name); + goto shithappens; + } + return pair; + +shithappens: + while (pair != NULL) { + rpair = pair->next; + free(pair); + pair = rpair; + } + return NULL; +} + +/* + * Function: rc_avpair_get + * + * Purpose: Find the first attribute value-pair (which matches the given + * attribute) from the specified value-pair list. + * + * Returns: found value_pair + * + */ + +VALUE_PAIR *rc_avpair_get (VALUE_PAIR *vp, int attrid, int vendorpec) +{ + for (; vp != NULL && !(ATTRID(vp->attribute) == ATTRID(attrid) && + VENDOR(vp->attribute) == vendorpec); vp = vp->next) + { + continue; + } + return vp; +} + +/* + * Function: rc_avpair_insert + * + * Purpose: Given the address of an existing list "a" and a pointer + * to an entry "p" in that list, add the value pair "b" to + * the "a" list after the "p" entry. If "p" is NULL, add + * the value pair "b" to the end of "a". + * + */ + +void rc_avpair_insert (VALUE_PAIR **a, VALUE_PAIR *p, VALUE_PAIR *b) +{ + VALUE_PAIR *this_node = NULL; + VALUE_PAIR *vp; + + if (b->next != NULL) + { + rc_log(LOG_CRIT, "rc_avpair_insert: value pair (0x%p) next ptr. (0x%p) not NULL", b, b->next); + abort (); + } + + if (*a == NULL) + { + *a = b; + return; + } + + vp = *a; + + if ( p == NULL) /* run to end of "a" list */ + { + while (vp != NULL) + { + this_node = vp; + vp = vp->next; + } + } + else /* look for the "p" entry in the "a" list */ + { + this_node = *a; + while (this_node != NULL) + { + if (this_node == p) + { + break; + } + this_node = this_node->next; + } + } + + b->next = this_node->next; + this_node->next = b; + + return; +} + +/* + * Function: rc_avpair_free + * + * Purpose: frees all value_pairs in the list + * + */ + +void rc_avpair_free (VALUE_PAIR *pair) +{ + VALUE_PAIR *next; + + while (pair != NULL) + { + next = pair->next; + free (pair); + pair = next; + } +} + +/* + * Function: rc_fieldcpy + * + * Purpose: Copy a data field from the buffer. Advance the buffer + * past the data field. Ensure that no more than len - 1 + * bytes are copied and that resulting string is terminated + * with '\0'. + * + */ + +static void +rc_fieldcpy(char *string, char const **uptr, char const *stopat, size_t len) +{ + char const *ptr, *estring; + + ptr = *uptr; + estring = string + len - 1; + if (*ptr == '"') + { + ptr++; + while (*ptr != '"' && *ptr != '\0' && *ptr != '\n') + { + if (string < estring) + *string++ = *ptr; + ptr++; + } + if (*ptr == '"') + { + ptr++; + } + *string = '\0'; + *uptr = ptr; + return; + } + + while (*ptr != '\0' && strchr(stopat, *ptr) == NULL) + { + if (string < estring) + *string++ = *ptr; + ptr++; + } + *string = '\0'; + *uptr = ptr; + return; +} + + +/* + * Function: rc_avpair_parse + * + * Purpose: parses the buffer to extract the attribute-value pairs. + * + * Returns: 0 = successful parse of attribute-value pair, + * -1 = syntax (or other) error detected. + * + */ + +#define PARSE_MODE_NAME 0 +#define PARSE_MODE_EQUAL 1 +#define PARSE_MODE_VALUE 2 +#define PARSE_MODE_INVALID 3 + +int rc_avpair_parse (rc_handle const *rh, char const *buffer, VALUE_PAIR **first_pair) +{ + int mode; + char attrstr[AUTH_ID_LEN]; + char valstr[AUTH_STRING_LEN + 1], *p; + DICT_ATTR *attr = NULL; + DICT_VALUE *dval; + VALUE_PAIR *pair; + VALUE_PAIR *link; + struct tm *tm; + time_t timeval; + + mode = PARSE_MODE_NAME; + while (*buffer != '\n' && *buffer != '\0') + { + if (*buffer == ' ' || *buffer == '\t') + { + buffer++; + continue; + } + + switch (mode) + { + case PARSE_MODE_NAME: /* Attribute Name */ + rc_fieldcpy (attrstr, &buffer, " \t\n=,", sizeof(attrstr)); + if ((attr = + rc_dict_findattr (rh, attrstr)) == NULL) + { + rc_log(LOG_ERR, "rc_avpair_parse: unknown attribute"); + if (*first_pair) { + rc_avpair_free(*first_pair); + *first_pair = NULL; + } + return -1; + } + mode = PARSE_MODE_EQUAL; + break; + + case PARSE_MODE_EQUAL: /* Equal sign */ + if (*buffer == '=') + { + mode = PARSE_MODE_VALUE; + buffer++; + } + else + { + rc_log(LOG_ERR, "rc_avpair_parse: missing or misplaced equal sign"); + if (*first_pair) { + rc_avpair_free(*first_pair); + *first_pair = NULL; + } + return -1; + } + break; + + case PARSE_MODE_VALUE: /* Value */ + rc_fieldcpy (valstr, &buffer, " \t\n,", sizeof(valstr)); + + if ((pair = malloc (sizeof (VALUE_PAIR))) == NULL) + { + rc_log(LOG_CRIT, "rc_avpair_parse: out of memory"); + if (*first_pair) { + rc_avpair_free(*first_pair); + *first_pair = NULL; + } + return -1; + } + strcpy (pair->name, attr->name); + pair->attribute = attr->value; + pair->type = attr->type; + + switch (pair->type) + { + + case PW_TYPE_STRING: + strcpy (pair->strvalue, valstr); + pair->lvalue = (uint32_t)strlen(valstr); + break; + + case PW_TYPE_INTEGER: + if (isdigit (*valstr)) + { + pair->lvalue = atoi (valstr); + } + else + { + if ((dval = rc_dict_findval (rh, valstr)) + == NULL) + { + rc_log(LOG_ERR, "rc_avpair_parse: unknown attribute value: %s", valstr); + if (*first_pair) { + rc_avpair_free(*first_pair); + *first_pair = NULL; + } + free (pair); + return -1; + } + else + { + pair->lvalue = dval->value; + } + } + break; + + case PW_TYPE_IPADDR: + pair->lvalue = rc_get_ipaddr(valstr); + break; + + case PW_TYPE_IPV6ADDR: + if (inet_pton(AF_INET6, valstr, pair->strvalue) == 0) { + rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv6 address %s", valstr); + free(pair); + return -1; + } + pair->lvalue = 16; + break; + + case PW_TYPE_IPV6PREFIX: + p = strchr(valstr, '/'); + if (p == NULL) { + rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv6 prefix %s", valstr); + free(pair); + return -1; + } + *p = 0; + p++; + pair->strvalue[0] = 0; + pair->strvalue[1] = atoi(p); + + if (inet_pton(AF_INET6, valstr, pair->strvalue+2) == 0) { + rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv6 prefix %s", valstr); + free(pair); + return -1; + } + pair->lvalue = 2+16; + break; + + case PW_TYPE_DATE: + timeval = time (0); + tm = localtime (&timeval); + tm->tm_hour = 0; + tm->tm_min = 0; + tm->tm_sec = 0; + rc_str2tm (valstr, tm); +#ifdef TIMELOCAL + pair->lvalue = (uint32_t) timelocal (tm); +#else /* TIMELOCAL */ + pair->lvalue = (uint32_t) mktime (tm); +#endif /* TIMELOCAL */ + break; + + default: + rc_log(LOG_ERR, "rc_avpair_parse: unknown attribute type %d", pair->type); + if (*first_pair) { + rc_avpair_free(*first_pair); + *first_pair = NULL; + } + free (pair); + return -1; + } + + /* XXX: Fix up Digest-Attributes */ + switch (pair->attribute) { + case PW_DIGEST_REALM: + case PW_DIGEST_NONCE: + case PW_DIGEST_METHOD: + case PW_DIGEST_URI: + case PW_DIGEST_QOP: + case PW_DIGEST_ALGORITHM: + case PW_DIGEST_BODY_DIGEST: + case PW_DIGEST_CNONCE: + case PW_DIGEST_NONCE_COUNT: + case PW_DIGEST_USER_NAME: + /* overlapping! */ + if (pair->lvalue > AUTH_STRING_LEN - 2) + pair->lvalue = AUTH_STRING_LEN - 2; + memmove(&pair->strvalue[2], &pair->strvalue[0], pair->lvalue); + pair->strvalue[0] = pair->attribute - PW_DIGEST_REALM + 1; + pair->lvalue += 2; + pair->strvalue[1] = pair->lvalue; + pair->strvalue[pair->lvalue] = '\0'; + pair->attribute = PW_DIGEST_ATTRIBUTES; + } + + pair->next = NULL; + + if (*first_pair == NULL) + { + *first_pair = pair; + } + else + { + link = *first_pair; + while (link->next != NULL) + { + link = link->next; + } + link->next = pair; + } + + mode = PARSE_MODE_NAME; + break; + + default: + mode = PARSE_MODE_NAME; + break; + } + } + return 0; +} + +/* + * Function: rc_avpair_tostr + * + * Purpose: Translate an av_pair into two strings + * + * Returns: 0 on success, -1 on failure + * + */ + +int rc_avpair_tostr (rc_handle const *rh, VALUE_PAIR *pair, char *name, int ln, char *value, int lv) +{ + DICT_VALUE *dval; + char buffer[32]; + struct in_addr inad; + unsigned char *ptr; + + *name = *value = '\0'; + + if (!pair || pair->name[0] == '\0') { + rc_log(LOG_ERR, "rc_avpair_tostr: pair is NULL or empty"); + return -1; + } + + strncpy(name, pair->name, (size_t) ln); + + switch (pair->type) + { + case PW_TYPE_STRING: + lv--; + ptr = (unsigned char *) pair->strvalue; + if (pair->attribute == PW_DIGEST_ATTRIBUTES) { + pair->strvalue[*(ptr + 1)] = '\0'; + ptr += 2; + } + while (*ptr != '\0') + { + if (!(isprint (*ptr))) + { + snprintf (buffer, sizeof(buffer), "\\%03o", *ptr); + strncat(value, buffer, (size_t) lv); + lv -= 4; + if (lv < 0) break; + } + else + { + strncat(value, (char *)ptr, 1); + lv--; + if (lv <= 0) break; + } + ptr++; + } + break; + + case PW_TYPE_INTEGER: + dval = rc_dict_getval (rh, pair->lvalue, pair->name); + if (dval != NULL) + { + strncpy(value, dval->name, (size_t) lv-1); + } + else + { + snprintf(buffer, sizeof(buffer), "%ld", (long int)pair->lvalue); + strncpy(value, buffer, (size_t) lv); + } + break; + + case PW_TYPE_IPADDR: + inad.s_addr = htonl(pair->lvalue); + strncpy (value, inet_ntoa (inad), (size_t) lv-1); + break; + + case PW_TYPE_IPV6ADDR: + if (inet_ntop(AF_INET6, pair->strvalue, value, lv-1) == NULL) + return -1; + break; + + case PW_TYPE_IPV6PREFIX: { + uint8_t ip[16]; + uint8_t txt[48]; + if (pair->lvalue < 2) + return -1; + + memset(ip, 0, sizeof(ip)); + memcpy(ip, pair->strvalue+2, pair->lvalue-2); + + if (inet_ntop(AF_INET6, ip, txt, sizeof(txt)) == NULL) + return -1; + snprintf(value, lv-1, "%s/%u", txt, (unsigned)pair->strvalue[1]); + + break; + } + case PW_TYPE_DATE: + strftime (buffer, sizeof (buffer), "%m/%d/%y %H:%M:%S", + gmtime ((time_t *) & pair->lvalue)); + strncpy(value, buffer, lv-1); + break; + + default: + rc_log(LOG_ERR, "rc_avpair_tostr: unknown attribute type %d", pair->type); + return -1; + break; + } + + return 0; +} + +/* + * Function: rc_avpair_log + * + * Purpose: format sequence of attribute value pairs into printable + * string. The caller should provide a storage buffer and the buffer length. + * Returns pointer to provided storage buffer. + * + */ +char * +rc_avpair_log(rc_handle const *rh, VALUE_PAIR *pair, char *buf, size_t buf_len) +{ + size_t len, nlen; + VALUE_PAIR *vp; + char name[33], value[256]; + + len = 0; + for (vp = pair; vp != NULL; vp = vp->next) { + if (rc_avpair_tostr(rh, vp, name, sizeof(name), value, + sizeof(value)) == -1) + return NULL; + nlen = len + 32 + 3 + strlen(value) + 2 + 2; + if(nlen +#include +#include + +unsigned char rc_get_id(); + +/* + * Function: rc_buildreq + * + * Purpose: builds a skeleton RADIUS request using information from the + * config file. + * + */ + +void rc_buildreq(rc_handle const *rh, SEND_DATA *data, int code, char *server, unsigned short port, + char *secret, int timeout, int retries) +{ + data->server = server; + data->secret = secret; + data->svc_port = port; + data->seq_nbr = rc_get_id(); + data->timeout = timeout; + data->retries = retries; + data->code = code; +} + +/* + * Function: rc_get_id + * + * Purpose: generate random id + * + */ + +unsigned char rc_get_id() +{ + return (unsigned char)(random() & UCHAR_MAX); +} + +/* + * Function: rc_aaa + * + * Purpose: Builds an authentication/accounting request for port id client_port + * with the value_pairs send and submits it to a server + * + * Returns: received value_pairs in received, messages from the server in msg + * and 0 on success, negative on failure as return value + * + */ + +int rc_aaa(rc_handle *rh, uint32_t client_port, VALUE_PAIR *send, VALUE_PAIR **received, + char *msg, int add_nas_port, int request_type) +{ + SEND_DATA data; + VALUE_PAIR *adt_vp = NULL; + int result; + int i, skip_count; + SERVER *aaaserver; + int timeout = rc_conf_int(rh, "radius_timeout"); + int retries = rc_conf_int(rh, "radius_retries"); + int radius_deadtime = rc_conf_int(rh, "radius_deadtime"); + double start_time = 0; + double now = 0; + time_t dtime; + + if (request_type != PW_ACCOUNTING_REQUEST) { + aaaserver = rc_conf_srv(rh, "authserver"); + } else { + aaaserver = rc_conf_srv(rh, "acctserver"); + } + if (aaaserver == NULL) + return ERROR_RC; + + data.send_pairs = send; + data.receive_pairs = NULL; + + if (add_nas_port != 0) { + /* + * Fill in NAS-Port + */ + if (rc_avpair_add(rh, &(data.send_pairs), PW_NAS_PORT, + &client_port, 0, 0) == NULL) + return ERROR_RC; + } + + if (request_type == PW_ACCOUNTING_REQUEST) { + /* + * Fill in Acct-Delay-Time + */ + dtime = 0; + now = rc_getctime(); + adt_vp = rc_avpair_get(data.send_pairs, PW_ACCT_DELAY_TIME, 0); + if (adt_vp == NULL) { + adt_vp = rc_avpair_add(rh, &(data.send_pairs), + PW_ACCT_DELAY_TIME, &dtime, 0, 0); + if (adt_vp == NULL) + return ERROR_RC; + start_time = now; + } else { + start_time = now - adt_vp->lvalue; + } + } + + skip_count = 0; + result = ERROR_RC; + for (i=0; (i < aaaserver->max) && (result != OK_RC) && (result != BADRESP_RC) + ; i++, now = rc_getctime()) + { + if (aaaserver->deadtime_ends[i] != -1 && + aaaserver->deadtime_ends[i] > start_time) { + skip_count++; + continue; + } + if (data.receive_pairs != NULL) { + rc_avpair_free(data.receive_pairs); + data.receive_pairs = NULL; + } + rc_buildreq(rh, &data, request_type, aaaserver->name[i], + aaaserver->port[i], aaaserver->secret[i], timeout, retries); + + if (request_type == PW_ACCOUNTING_REQUEST) { + dtime = now - start_time; + rc_avpair_assign(adt_vp, &dtime, 0); + } + + result = rc_send_server (rh, &data, msg); + if (result == TIMEOUT_RC && radius_deadtime > 0) + aaaserver->deadtime_ends[i] = start_time + (double)radius_deadtime; + } + if (result == OK_RC || result == BADRESP_RC || skip_count == 0) + goto exit; + + result = ERROR_RC; + for (i=0; (i < aaaserver->max) && (result != OK_RC) && (result != BADRESP_RC) + ; i++) + { + if (aaaserver->deadtime_ends[i] == -1 || + aaaserver->deadtime_ends[i] <= start_time) { + continue; + } + if (data.receive_pairs != NULL) { + rc_avpair_free(data.receive_pairs); + data.receive_pairs = NULL; + } + rc_buildreq(rh, &data, request_type, aaaserver->name[i], + aaaserver->port[i], aaaserver->secret[i], timeout, retries); + + if (request_type == PW_ACCOUNTING_REQUEST) { + dtime = rc_getctime() - start_time; + rc_avpair_assign(adt_vp, &dtime, 0); + } + + result = rc_send_server (rh, &data, msg); + if (result != TIMEOUT_RC) + aaaserver->deadtime_ends[i] = -1; + } + +exit: + if (request_type != PW_ACCOUNTING_REQUEST) { + *received = data.receive_pairs; + } else { + rc_avpair_free(data.receive_pairs); + } + + return result; +} + +/* + * Function: rc_auth + * + * Purpose: Builds an authentication request for port id client_port + * with the value_pairs send and submits it to a server + * + * Returns: received value_pairs in received, messages from the server in msg (if non-NULL), + * and 0 on success, negative on failure as return value + * + */ + +int rc_auth(rc_handle *rh, uint32_t client_port, VALUE_PAIR *send, VALUE_PAIR **received, + char *msg) +{ + + return rc_aaa(rh, client_port, send, received, msg, 1, PW_ACCESS_REQUEST); +} + +/* + * Function: rc_auth_proxy + * + * Purpose: Builds an authentication request + * with the value_pairs send and submits it to a server. + * Works for a proxy; does not add IP address, and does + * does not rely on config file. + * + * Returns: received value_pairs in received, messages from the server in msg (if non-NULL) + * and 0 on success, negative on failure as return value + * + */ + +int rc_auth_proxy(rc_handle *rh, VALUE_PAIR *send, VALUE_PAIR **received, char *msg) +{ + + return rc_aaa(rh, 0, send, received, msg, 0, PW_ACCESS_REQUEST); +} + + +/* + * Function: rc_acct + * + * Purpose: Builds an accounting request for port id client_port + * with the value_pairs send + * + * Remarks: NAS-IP-Address, NAS-Port and Acct-Delay-Time get filled + * in by this function, the rest has to be supplied. + */ + +int rc_acct(rc_handle *rh, uint32_t client_port, VALUE_PAIR *send) +{ + + return rc_aaa(rh, client_port, send, NULL, NULL, 1, PW_ACCOUNTING_REQUEST); +} + +/* + * Function: rc_acct_proxy + * + * Purpose: Builds an accounting request with the value_pairs send + * + */ + +int rc_acct_proxy(rc_handle *rh, VALUE_PAIR *send) +{ + + return rc_aaa(rh, 0, send, NULL, NULL, 0, PW_ACCOUNTING_REQUEST); +} + +/* + * Function: rc_check + * + * Purpose: ask the server hostname on the specified port for a + * status message + * + */ + +int rc_check(rc_handle *rh, char *host, char *secret, unsigned short port, char *msg) +{ + SEND_DATA data; + int result; + uint32_t service_type; + int timeout = rc_conf_int(rh, "radius_timeout"); + int retries = rc_conf_int(rh, "radius_retries"); + + data.send_pairs = data.receive_pairs = NULL; + + /* + * Fill in Service-Type + */ + + service_type = PW_ADMINISTRATIVE; + rc_avpair_add(rh, &(data.send_pairs), PW_SERVICE_TYPE, &service_type, 0, 0); + + rc_buildreq(rh, &data, PW_STATUS_SERVER, host, port, secret, timeout, retries); + result = rc_send_server (rh, &data, msg); + + rc_avpair_free(data.receive_pairs); + + return result; +} diff --git a/src/plugins/vbng/lib/clientid.c b/src/plugins/vbng/lib/clientid.c new file mode 100644 index 0000000..6901a04 --- /dev/null +++ b/src/plugins/vbng/lib/clientid.c @@ -0,0 +1,146 @@ +/* + * $Id: clientid.c,v 1.7 2007/07/11 17:29:29 cparker Exp $ + * + * Copyright (C) 1995,1996,1997 Lars Fenneberg + * + * See the file COPYRIGHT for the respective terms and conditions. + * If the file is missing contact me at lf@elemental.net + * and I'll send you a copy. + * + */ + +#include +#include +#include + +struct map2id_s { + char *name; + uint32_t id; + + struct map2id_s *next; +}; + +/* + * Function: rc_read_mapfile + * + * Purpose: Read in the ttyname to port id map file + * + * Arguments: the file name of the map file + * + * Returns: zero on success, negative integer on failure + */ + +int rc_read_mapfile(rc_handle *rh, char const *filename) +{ + char buffer[1024]; + FILE *mapfd; + char *c, *name, *id, *q; + struct map2id_s *p; + int lnr = 0; + + if ((mapfd = fopen(filename,"r")) == NULL) + { + rc_log(LOG_ERR,"rc_read_mapfile: can't read %s: %s", filename, strerror(errno)); + return -1; + } + +#define SKIP(p) while(*p && isspace(*p)) p++; + + while (fgets(buffer, sizeof(buffer), mapfd) != NULL) + { + lnr++; + + q = buffer; + + SKIP(q); + + if ((*q == '\n') || (*q == '#') || (*q == '\0')) + continue; + + if (( c = strchr(q, ' ')) || (c = strchr(q,'\t'))) { + + *c = '\0'; c++; + SKIP(c); + + name = q; + id = c; + + if ((p = (struct map2id_s *)malloc(sizeof(*p))) == NULL) { + rc_log(LOG_CRIT,"rc_read_mapfile: out of memory"); + fclose(mapfd); + return -1; + } + + p->name = strdup(name); + p->id = atoi(id); + p->next = rh->map2id_list; + rh->map2id_list = p; + + } else { + + rc_log(LOG_ERR, "rc_read_mapfile: malformed line in %s, line %d", filename, lnr); + fclose(mapfd); + return -1; + + } + } + +#undef SKIP + + fclose(mapfd); + + return 0; +} + +/* + * Function: rc_map2id + * + * Purpose: Map ttyname to port id + * + * Arguments: full pathname of the tty + * + * Returns: port id, zero if no entry found + */ + +uint32_t rc_map2id(rc_handle const *rh, char const *name) +{ + struct map2id_s *p; + char ttyname[PATH_MAX]; + + *ttyname = '\0'; + if (*name != '/') + strcpy(ttyname, "/dev/"); + + strncat(ttyname, name, sizeof(ttyname)-strlen(ttyname)-1); + + for(p = rh->map2id_list; p; p = p->next) + if (!strcmp(ttyname, p->name)) return p->id; + + rc_log(LOG_WARNING,"rc_map2id: can't find tty %s in map database", ttyname); + + return 0; +} + +/* + * Function: rc_map2id_free + * + * Purpose: Free allocated map2id list + * + * Arguments: Radius Client handle + */ + +void +rc_map2id_free(rc_handle *rh) +{ + struct map2id_s *p, *np; + + if (rh->map2id_list == NULL) + return; + + for(p = rh->map2id_list; p != NULL; p = np) { + np = p->next; + free(p->name); + free(p); + } + rh->map2id_list = NULL; +} diff --git a/src/plugins/vbng/lib/config.c b/src/plugins/vbng/lib/config.c new file mode 100644 index 0000000..1db7860 --- /dev/null +++ b/src/plugins/vbng/lib/config.c @@ -0,0 +1,925 @@ +/* + * $Id: config.c,v 1.23 2010/04/28 14:26:15 aland Exp $ + * + * Copyright (C) 1995,1996,1997 Lars Fenneberg + * + * Copyright 1992 Livingston Enterprises, Inc. + * + * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan + * and Merit Network, Inc. All Rights Reserved + * + * See the file COPYRIGHT for the respective terms and conditions. + * If the file is missing contact me at lf@elemental.net + * and I'll send you a copy. + * + */ + +#include +#include +#include +#include + +/* + * Function: find_option + * + * Purpose: find an option in the option list + * + * Returns: pointer to option on success, NULL otherwise + */ + +static OPTION *find_option(rc_handle const *rh, char const *optname, unsigned int type) +{ + int i; + + /* there're so few options that a binary search seems not necessary */ + for (i = 0; i < NUM_OPTIONS; i++) { + if (!strcmp(rh->config_options[i].name, optname) && + (rh->config_options[i].type & type)) + { + return &rh->config_options[i]; + } + } + + return NULL; +} + +/* + * Function: set_option_... + * + * Purpose: set a specific option doing type conversions + * + * Returns: 0 on success, -1 on failure + */ + +static int set_option_str(char const *filename, int line, OPTION *option, char const *p) +{ + if (p) { + option->val = (void *) strdup(p); + if (option->val == NULL) { + rc_log(LOG_CRIT, "read_config: out of memory"); + return -1; + } + } else { + option->val = NULL; + } + + return 0; +} + +static int set_option_int(char const *filename, int line, OPTION *option, char const *p) +{ + int *iptr; + + if (p == NULL) { + rc_log(LOG_ERR, "%s: line %d: bogus option value", filename, line); + return -1; + } + + if ((iptr = malloc(sizeof(*iptr))) == NULL) { + rc_log(LOG_CRIT, "read_config: out of memory"); + return -1; + } + + *iptr = atoi(p); + option->val = (void *) iptr; + + return 0; +} + +static int set_option_srv(char const *filename, int line, OPTION *option, char const *p) +{ + SERVER *serv; + char *p_pointer; + char *p_dupe; + char *p_save; + char *q; + char *s; + struct servent *svp; + + p_dupe = strdup(p); + + if (p_dupe == NULL) { + rc_log(LOG_ERR, "%s: line %d: Invalid option or memory failure", filename, line); + return -1; + } + + serv = (SERVER *) option->val; + if (serv == NULL) { + DEBUG(LOG_ERR, "option->val / server is NULL, allocating memory"); + serv = malloc(sizeof(*serv)); + if (serv == NULL) { + rc_log(LOG_CRIT, "read_config: out of memory"); + free(p_dupe); + return -1; + } + memset(serv, 0, sizeof(*serv)); + serv->max = 0; + } + + p_pointer = strtok_r(p_dupe, ", \t", &p_save); + + /* Check to see if we have 'servername:port' syntax */ + if ((q = strchr(p_pointer,':')) != NULL) { + *q = '\0'; + q++; + + /* Check to see if we have 'servername:port:secret' syntax */ + if((s = strchr(q,':')) != NULL) { + *s = '\0'; + s++; + serv->secret[serv->max] = strdup(s); + if (serv->secret[serv->max] == NULL) { + rc_log(LOG_CRIT, "read_config: out of memory"); + if (option->val == NULL) { + free(p_dupe); + free(serv); + } + return -1; + } + } + } + if(q && strlen(q) > 0) { + serv->port[serv->max] = atoi(q); + } else { + if (!strcmp(option->name,"authserver")) + if ((svp = getservbyname ("radius", "udp")) == NULL) + serv->port[serv->max] = PW_AUTH_UDP_PORT; + else + serv->port[serv->max] = ntohs ((unsigned int) svp->s_port); + else if (!strcmp(option->name, "acctserver")) + if ((svp = getservbyname ("radacct", "udp")) == NULL) + serv->port[serv->max] = PW_ACCT_UDP_PORT; + else + serv->port[serv->max] = ntohs ((unsigned int) svp->s_port); + else { + rc_log(LOG_ERR, "%s: line %d: no default port for %s", filename, line, option->name); + if (option->val == NULL) { + free(p_dupe); + free(serv); + } + return -1; + } + } + + serv->name[serv->max] = strdup(p_pointer); + if (serv->name[serv->max] == NULL) { + rc_log(LOG_CRIT, "read_config: out of memory"); + if (option->val == NULL) { + free(p_dupe); + free(serv); + } + return -1; + } + free(p_dupe); + + serv->deadtime_ends[serv->max] = -1; + serv->max++; + + if (option->val == NULL) + option->val = (void *)serv; + + return 0; +} + +static int set_option_auo(char const *filename, int line, OPTION *option, char const *p) +{ + int *iptr; + char *p_dupe = NULL; + char *p_pointer = NULL; + char *p_save = NULL; + + p_dupe = strdup(p); + + if (p_dupe == NULL) { + rc_log(LOG_WARNING, "%s: line %d: bogus option value", filename, line); + return -1; + } + + if ((iptr = malloc(sizeof(iptr))) == NULL) { + rc_log(LOG_CRIT, "read_config: out of memory"); + free(p_dupe); + return -1; + } + + *iptr = 0; + /*if(strstr(p_dupe,", \t") != NULL) {*/ + p_pointer = strtok_r(p_dupe, ", \t", &p_save); + /*}*/ + + if (!strncmp(p_pointer, "local", 5)) + *iptr = AUTH_LOCAL_FST; + else if (!strncmp(p_pointer, "radius", 6)) + *iptr = AUTH_RADIUS_FST; + else { + rc_log(LOG_ERR,"%s: auth_order: unknown keyword: %s", filename, p); + free(iptr); + free(p_dupe); + return -1; + } + + p_pointer = strtok_r(NULL, ", \t", &p_save); + + if (p_pointer && (*p_pointer != '\0')) { + if ((*iptr & AUTH_RADIUS_FST) && !strcmp(p_pointer, "local")) + *iptr = (*iptr) | AUTH_LOCAL_SND; + else if ((*iptr & AUTH_LOCAL_FST) && !strcmp(p_pointer, "radius")) + *iptr = (*iptr) | AUTH_RADIUS_SND; + else { + rc_log(LOG_ERR,"%s: auth_order: unknown or unexpected keyword: %s", filename, p); + free(iptr); + free(p_dupe); + return -1; + } + } + + option->val = (void *) iptr; + + free(p_dupe); + return 0; +} + + +/* Function: rc_add_config + * + * Purpose: allow a config option to be added to rc_handle from inside a program + * + * Returns: 0 on success, -1 on failure + */ + +int rc_add_config(rc_handle *rh, char const *option_name, char const *option_val, char const *source, int line) +{ + OPTION *option; + + if ((option = find_option(rh, option_name, OT_ANY)) == NULL) + { + rc_log(LOG_ERR, "ERROR: unrecognized option: %s", option_name); + return -1; + } + + if (option->status != ST_UNDEF) + { + rc_log(LOG_ERR, "ERROR: duplicate option: %s", option_name); + return -1; + } + + switch (option->type) { + case OT_STR: + if (set_option_str(source, line, option, option_val) < 0) { + return -1; + } + break; + case OT_INT: + if (set_option_int(source, line, option, option_val) < 0) { + return -1; + } + break; + case OT_SRV: + if (set_option_srv(source, line, option, option_val) < 0) { + return -1; + } + break; + case OT_AUO: + if (set_option_auo(source, line, option, option_val) < 0) { + return -1; + } + break; + default: + rc_log(LOG_CRIT, "rc_add_config: impossible case branch!"); + abort(); + } + return 0; +} + +/* + * Function: rc_config_init + * + * Purpose: initialize the configuration structure from an external program. For use when not + * running a standalone client that reads from a config file. + * + * Returns: rc_handle on success, NULL on failure + */ + +rc_handle * +rc_config_init(rc_handle *rh) +{ + int i; + SERVER *authservers; + SERVER *acctservers; + OPTION *acct; + OPTION *auth; + + rh->config_options = malloc(sizeof(config_options_default)); + if (rh->config_options == NULL) + { + rc_log(LOG_CRIT, "rc_config_init: out of memory"); + rc_destroy(rh); + return NULL; + } + memcpy(rh->config_options, &config_options_default, sizeof(config_options_default)); + + acct = find_option(rh, "acctserver", OT_ANY); + auth = find_option(rh, "authserver", OT_ANY); + authservers = malloc(sizeof(SERVER)); + acctservers = malloc(sizeof(SERVER)); + + if(authservers == NULL || acctservers == NULL) + { + rc_log(LOG_CRIT, "rc_config_init: error initializing server structs"); + rc_destroy(rh); + if(authservers) free(authservers); + if(acctservers) free(acctservers); + return NULL; + } + + + authservers->max = 0; + acctservers->max = 0; + + for(i=0; i < SERVER_MAX; i++) + { + authservers->name[i] = NULL; + authservers->secret[i] = NULL; + acctservers->name[i] = NULL; + acctservers->secret[i] = NULL; + } + acct->val = acctservers; + auth->val = authservers; + return rh; +} + + +/* + * Function: rc_read_config + * + * Purpose: read the global config file + * + * Returns: new rc_handle on success, NULL when failure + */ + +rc_handle * +rc_read_config(char const *filename) +{ + FILE *configfd; + char buffer[512], *p; + OPTION *option; + int line; + size_t pos; + rc_handle *rh; + + srandom((unsigned int)(time(NULL)+getpid())); + + rh = rc_new(); + if (rh == NULL) + return NULL; + + rh->config_options = malloc(sizeof(config_options_default)); + if (rh->config_options == NULL) { + rc_log(LOG_CRIT, "rc_read_config: out of memory"); + rc_destroy(rh); + return NULL; + } + memcpy(rh->config_options, &config_options_default, sizeof(config_options_default)); + + if ((configfd = fopen(filename,"r")) == NULL) + { + rc_log(LOG_ERR,"rc_read_config: can't open %s: %s", filename, strerror(errno)); + rc_destroy(rh); + return NULL; + } + + line = 0; + while ((fgets(buffer, sizeof(buffer), configfd) != NULL)) + { + line++; + p = buffer; + + if ((*p == '\n') || (*p == '#') || (*p == '\0')) + continue; + + p[strlen(p)-1] = '\0'; + + + if ((pos = strcspn(p, "\t ")) == 0) { + rc_log(LOG_ERR, "%s: line %d: bogus format: %s", filename, line, p); + fclose(configfd); + rc_destroy(rh); + return NULL; + } + + p[pos] = '\0'; + + if ((option = find_option(rh, p, OT_ANY)) == NULL) { + rc_log(LOG_ERR, "%s: line %d: unrecognized keyword: %s", filename, line, p); + fclose(configfd); + rc_destroy(rh); + return NULL; + } + + if (option->status != ST_UNDEF) { + rc_log(LOG_ERR, "%s: line %d: duplicate option line: %s", filename, line, p); + fclose(configfd); + rc_destroy(rh); + return NULL; + } + + p += pos+1; + while (isspace(*p)) + p++; + pos = strlen(p) - 1; + while(pos != 0 && isspace(p[pos])) + pos--; + p[pos + 1] = '\0'; + + switch (option->type) { + case OT_STR: + if (set_option_str(filename, line, option, p) < 0) { + fclose(configfd); + rc_destroy(rh); + return NULL; + } + break; + case OT_INT: + if (set_option_int(filename, line, option, p) < 0) { + fclose(configfd); + rc_destroy(rh); + return NULL; + } + break; + case OT_SRV: + if (set_option_srv(filename, line, option, p) < 0) { + fclose(configfd); + rc_destroy(rh); + return NULL; + } + break; + case OT_AUO: + if (set_option_auo(filename, line, option, p) < 0) { + fclose(configfd); + rc_destroy(rh); + return NULL; + } + break; + default: + rc_log(LOG_CRIT, "rc_read_config: impossible case branch!"); + abort(); + } + } + fclose(configfd); + + if (test_config(rh, filename) == -1) { + rc_destroy(rh); + return NULL; + } + return rh; +} + +/* + * Function: rc_conf_str, rc_conf_int, rc_conf_src + * + * Purpose: get the value of a config option + * + * Returns: config option value + */ + +char *rc_conf_str(rc_handle const *rh, char const *optname) +{ + OPTION *option; + + option = find_option(rh, optname, OT_STR); + + if (option != NULL) { + return (char *)option->val; + } else { + rc_log(LOG_CRIT, "rc_conf_str: unkown config option requested: %s", optname); + abort(); + return NULL; + } +} + +int rc_conf_int(rc_handle const *rh, char const *optname) +{ + OPTION *option; + + option = find_option(rh, optname, OT_INT|OT_AUO); + + if (option != NULL) { + if (option->val) { + return *((int *)option->val); + } else { + rc_log(LOG_ERR, "rc_conf_int: config option %s was not set", optname); + return 0; + } + } else { + rc_log(LOG_CRIT, "rc_conf_int: unkown config option requested: %s", optname); + abort(); + return 0; + } +} + +SERVER *rc_conf_srv(rc_handle const *rh, char const *optname) +{ + OPTION *option; + + option = find_option(rh, optname, OT_SRV); + + if (option != NULL) { + return (SERVER *)option->val; + } else { + rc_log(LOG_CRIT, "rc_conf_srv: unkown config option requested: %s", optname); + abort(); + return NULL; + } +} + +/* + * Function: test_config + * + * Purpose: test the configuration the user supplied + * + * Returns: 0 on success, -1 when failure + */ + +int test_config(rc_handle const *rh, char const *filename) +{ +#if 0 + struct stat st; + char *file; +#endif + + if (!(rc_conf_srv(rh, "authserver")->max)) + { + rc_log(LOG_ERR,"%s: no authserver specified", filename); + return -1; + } + if (!(rc_conf_srv(rh, "acctserver")->max)) + { + rc_log(LOG_ERR,"%s: no acctserver specified", filename); + return -1; + } + if (!rc_conf_str(rh, "servers")) + { + rc_log(LOG_ERR,"%s: no servers file specified", filename); + return -1; + } + if (!rc_conf_str(rh, "dictionary")) + { + rc_log(LOG_ERR,"%s: no dictionary specified", filename); + return -1; + } + + if (rc_conf_int(rh, "radius_timeout") <= 0) + { + rc_log(LOG_ERR,"%s: radius_timeout <= 0 is illegal", filename); + return -1; + } + if (rc_conf_int(rh, "radius_retries") <= 0) + { + rc_log(LOG_ERR,"%s: radius_retries <= 0 is illegal", filename); + return -1; + } + if (rc_conf_int(rh, "radius_deadtime") < 0) + { + rc_log(LOG_ERR,"%s: radius_deadtime is illegal", filename); + return -1; + } +#if 0 + file = rc_conf_str(rh, "login_local"); + if (stat(file, &st) == 0) + { + if (!S_ISREG(st.st_mode)) { + rc_log(LOG_ERR,"%s: not a regular file: %s", filename, file); + return -1; + } + } else { + rc_log(LOG_ERR,"%s: file not found: %s", filename, file); + return -1; + } + file = rc_conf_str(rh, "login_radius"); + if (stat(file, &st) == 0) + { + if (!S_ISREG(st.st_mode)) { + rc_log(LOG_ERR,"%s: not a regular file: %s", filename, file); + return -1; + } + } else { + rc_log(LOG_ERR,"%s: file not found: %s", filename, file); + return -1; + } +#endif + + if (rc_conf_int(rh, "login_tries") <= 0) + { + rc_log(LOG_ERR,"%s: login_tries <= 0 is illegal", filename); + return -1; + } + if (rc_conf_str(rh, "seqfile") == NULL) + { + rc_log(LOG_ERR,"%s: seqfile not specified", filename); + return -1; + } + if (rc_conf_int(rh, "login_timeout") <= 0) + { + rc_log(LOG_ERR,"%s: login_timeout <= 0 is illegal", filename); + return -1; + } + if (rc_conf_str(rh, "mapfile") == NULL) + { + rc_log(LOG_ERR,"%s: mapfile not specified", filename); + return -1; + } + if (rc_conf_str(rh, "nologin") == NULL) + { + rc_log(LOG_ERR,"%s: nologin not specified", filename); + return -1; + } + + return 0; +} + +/* + * Function: rc_find_match + * + * Purpose: see if ip_addr is one of the ip addresses of hostname + * + * Returns: 0 on success, -1 when failure + * + */ + +static int find_match (uint32_t *ip_addr, char const *hostname) +{ + + uint32_t addr; + char **paddr; + struct hostent *hp; + + if (rc_good_ipaddr (hostname) == 0) + { + if (*ip_addr == ntohl(inet_addr (hostname))) + { + return 0; + } + return -1; + } + + if ((hp = rc_gethostbyname(hostname)) == NULL) + { + return -1; + } + + for (paddr = hp->h_addr_list; *paddr; paddr++) + { + addr = ** (uint32_t **) paddr; + if (ntohl(addr) == *ip_addr) + { + return 0; + } + } + return -1; +} + +/* + * Function: rc_ipaddr_local + * + * Purpose: checks if provided address is local address + * + * Returns: 0 if local, 1 if not local, -1 on failure + * + */ + +static int +rc_ipaddr_local(uint32_t ip_addr) +{ + int temp_sock, res, serrno; + struct sockaddr_in sin; + + temp_sock = socket(AF_INET, SOCK_DGRAM, 0); + if (temp_sock == -1) + return -1; + memset(&sin, '\0', sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = htonl(ip_addr); + sin.sin_port = htons(0); + res = bind(temp_sock, (struct sockaddr *)&sin, sizeof(sin)); + serrno = errno; + close(temp_sock); + if (res == 0) + return 0; + if (serrno == EADDRNOTAVAIL) + return 1; + return -1; +} + +/* + * Function: rc_is_myname + * + * Purpose: check if provided name refers to ourselves + * + * Returns: 0 if yes, 1 if no and -1 on failure + * + */ + +static int +rc_is_myname(char const *hostname) +{ + uint32_t addr; + char **paddr; + struct hostent *hp; + int res; + + if (rc_good_ipaddr(hostname) == 0) + return rc_ipaddr_local(ntohl(inet_addr(hostname))); + + if ((hp = rc_gethostbyname(hostname)) == NULL) + return -1; + for (paddr = hp->h_addr_list; *paddr; paddr++) { + addr = **(uint32_t **)paddr; + res = rc_ipaddr_local(ntohl(addr)); + if (res == 0 || res == -1) + return res; + } + return 1; +} + +/* + * Function: rc_find_server + * + * Purpose: locate a server in the rh config or if not found, check for a servers file + * + * Returns: 0 on success, -1 on failure + * + */ + +int rc_find_server (rc_handle const *rh, char const *server_name, uint32_t *ip_addr, char *secret) +{ + int i; + size_t len; + int result = 0; + FILE *clientfd; + char *h; + char *s; + char buffer[128]; + char hostnm[AUTH_ID_LEN + 1]; + char *buffer_save; + char *hostnm_save; + SERVER *authservers; + SERVER *acctservers; + + /* Lookup the IP address of the radius server */ + if ((*ip_addr = rc_get_ipaddr (server_name)) == (uint32_t) 0) + return -1; + + /* Check to see if the server secret is defined in the rh config */ + if( (authservers = rc_conf_srv(rh, "authserver")) != NULL ) + { + for( i = 0; i < authservers->max; i++ ) + { + if( (strncmp(server_name, authservers->name[i], strlen(server_name)) == 0) && + (authservers->secret[i] != NULL) ) + { + memset (secret, '\0', MAX_SECRET_LENGTH); + len = strlen (authservers->secret[i]); + if (len > MAX_SECRET_LENGTH) + { + len = MAX_SECRET_LENGTH; + } + strncpy (secret, authservers->secret[i], (size_t) len); + secret[MAX_SECRET_LENGTH] = '\0'; + return 0; + } + } + } + + if( (acctservers = rc_conf_srv(rh, "acctserver")) != NULL ) + { + for( i = 0; i < acctservers->max; i++ ) + { + if( (strncmp(server_name, acctservers->name[i], strlen(server_name)) == 0) && + (acctservers->secret[i] != NULL) ) + { + memset (secret, '\0', MAX_SECRET_LENGTH); + len = strlen (acctservers->secret[i]); + if (len > MAX_SECRET_LENGTH) + { + len = MAX_SECRET_LENGTH; + } + strncpy (secret, acctservers->secret[i], (size_t) len); + secret[MAX_SECRET_LENGTH] = '\0'; + return 0; + } + } + } + + /* We didn't find it in the rh_config or the servername is too long so look for a + * servers file to define the secret(s) + */ + + if ((clientfd = fopen (rc_conf_str(rh, "servers"), "r")) == NULL) + { + rc_log(LOG_ERR, "rc_find_server: couldn't open file: %s: %s", strerror(errno), rc_conf_str(rh, "servers")); + return -1; + } + + while (fgets (buffer, sizeof (buffer), clientfd) != NULL) + { + if (*buffer == '#') + continue; + + if ((h = strtok_r(buffer, " \t\n", &buffer_save)) == NULL) /* first hostname */ + continue; + + memset (hostnm, '\0', AUTH_ID_LEN); + len = strlen (h); + if (len > AUTH_ID_LEN) + { + len = AUTH_ID_LEN; + } + strncpy (hostnm, h, (size_t) len); + hostnm[AUTH_ID_LEN] = '\0'; + + if ((s = strtok_r (NULL, " \t\n", &buffer_save)) == NULL) /* and secret field */ + continue; + + memset (secret, '\0', MAX_SECRET_LENGTH); + len = strlen (s); + if (len > MAX_SECRET_LENGTH) + { + len = MAX_SECRET_LENGTH; + } + strncpy (secret, s, (size_t) len); + secret[MAX_SECRET_LENGTH] = '\0'; + + if (!strchr (hostnm, '/')) /* If single name form */ + { + if (find_match (ip_addr, hostnm) == 0) + { + result++; + break; + } + } + else /* / "paired" form */ + { + strtok_r(hostnm, "/", &hostnm_save); + if (rc_is_myname(hostnm) == 0) + { /* If we're the 1st name, target is 2nd */ + if (find_match (ip_addr, hostnm_save) == 0) + { + result++; + break; + } + } + else /* If we were 2nd name, target is 1st name */ + { + if (find_match (ip_addr, hostnm) == 0) + { + result++; + break; + } + } + } + } + fclose (clientfd); + if (result == 0) + { + memset (buffer, '\0', sizeof (buffer)); + memset (secret, '\0', MAX_SECRET_LENGTH); + rc_log(LOG_ERR, "rc_find_server: couldn't find RADIUS server %s in %s", + server_name, rc_conf_str(rh, "servers")); + return -1; + } + return 0; +} + +/* + * Function: rc_config_free + * + * Purpose: Free allocated config values + * + * Arguments: Radius Client handle + */ + +void +rc_config_free(rc_handle *rh) +{ + int i, j; + SERVER *serv; + + if (rh->config_options == NULL) + return; + + for (i = 0; i < NUM_OPTIONS; i++) { + if (rh->config_options[i].val == NULL) + continue; + if (rh->config_options[i].type == OT_SRV) { + serv = (SERVER *)rh->config_options[i].val; + for (j = 0; j < serv->max; j++){ + free(serv->name[j]); + if(serv->secret[j]) free(serv->secret[j]); + } + free(serv); + } else { + free(rh->config_options[i].val); + } + } + free(rh->config_options); + rh->config_options = NULL; +} diff --git a/src/plugins/vbng/lib/dict.c b/src/plugins/vbng/lib/dict.c new file mode 100644 index 0000000..84dbba0 --- /dev/null +++ b/src/plugins/vbng/lib/dict.c @@ -0,0 +1,519 @@ +/* + * $Id: dict.c,v 1.10 2007/07/11 17:29:29 cparker Exp $ + * + * Copyright (C) 1995,1996,1997 Lars Fenneberg + * + * Copyright 1992 Livingston Enterprises, Inc. + * + * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan + * and Merit Network, Inc. All Rights Reserved + * + * See the file COPYRIGHT for the respective terms and conditions. + * If the file is missing contact me at lf@elemental.net + * and I'll send you a copy. + * + */ + +#include +#include +#include + +/* + * Function: rc_read_dictionary + * + * Purpose: Initialize the dictionary. Read all ATTRIBUTES into + * the dictionary_attributes list. Read all VALUES into + * the dictionary_values list. + * + */ + +int rc_read_dictionary (rc_handle *rh, char const *filename) +{ + FILE *dictfd; + char dummystr[AUTH_ID_LEN]; + char namestr[AUTH_ID_LEN]; + char valstr[AUTH_ID_LEN]; + char attrstr[AUTH_ID_LEN]; + char typestr[AUTH_ID_LEN]; + char optstr[AUTH_ID_LEN]; + char *cp, *ifilename; + int line_no; + DICT_ATTR *attr; + DICT_VALUE *dval; + DICT_VENDOR *dvend; + char buffer[256]; + int value; + int type; + unsigned attr_vendorspec = 0; + + if ((dictfd = fopen (filename, "r")) == NULL) + { + rc_log(LOG_ERR, "rc_read_dictionary: couldn't open dictionary %s: %s", + filename, strerror(errno)); + return -1; + } + + line_no = 0; + while (fgets (buffer, sizeof (buffer), dictfd) != NULL) + { + line_no++; + + /* Skip empty space */ + if (*buffer == '#' || *buffer == '\0' || *buffer == '\n' || \ + *buffer == '\r') + { + continue; + } + + /* Strip out comments */ + cp = strchr(buffer, '#'); + if (cp != NULL) + { + *cp = '\0'; + } + + if (strncmp (buffer, "ATTRIBUTE", 9) == 0) + { + optstr[0] = '\0'; + /* Read the ATTRIBUTE line */ + if (sscanf (buffer, "%63s%63s%63s%63s%63s", dummystr, namestr, + valstr, typestr, optstr) < 4) + { + rc_log(LOG_ERR, "rc_read_dictionary: invalid attribute on line %d of dictionary %s", + line_no, filename); + fclose(dictfd); + return -1; + } + + /* + * Validate all entries + */ + if (strlen (namestr) > NAME_LENGTH) + { + rc_log(LOG_ERR, "rc_read_dictionary: invalid name length on line %d of dictionary %s", + line_no, filename); + fclose(dictfd); + return -1; + } + + if (!isdigit (*valstr)) + { + rc_log(LOG_ERR, + "rc_read_dictionary: invalid value on line %d of dictionary %s", + line_no, filename); + fclose(dictfd); + return -1; + } + value = atoi (valstr); + + if (strcmp (typestr, "string") == 0) + { + type = PW_TYPE_STRING; + } + else if (strcmp (typestr, "integer") == 0) + { + type = PW_TYPE_INTEGER; + } + else if (strcmp (typestr, "ipaddr") == 0) + { + type = PW_TYPE_IPADDR; + } + else if (strcmp (typestr, "ipv6addr") == 0) + { + type = PW_TYPE_IPV6ADDR; + } + else if (strcmp (typestr, "ipv6prefix") == 0) + { + type = PW_TYPE_IPV6PREFIX; + } + else if (strcmp (typestr, "date") == 0) + { + type = PW_TYPE_DATE; + } + else + { + rc_log(LOG_ERR, + "rc_read_dictionary: invalid type on line %d of dictionary %s", + line_no, filename); + fclose(dictfd); + return -1; + } + + dvend = NULL; + if (optstr[0] != '\0') { + char *cp1; + for (cp1 = optstr; cp1 != NULL; cp1 = cp) { + cp = strchr(cp1, ','); + if (cp != NULL) { + *cp = '\0'; + cp++; + } + if (strncmp(cp1, "vendor=", 7) == 0) + cp1 += 7; + dvend = rc_dict_findvend(rh, cp1); + if (dvend == NULL) { + rc_log(LOG_ERR, + "rc_read_dictionary: unknown Vendor-Id %s on line %d of dictionary %s", + cp1, line_no, filename); + fclose(dictfd); + return -1; + } + } + } + + /* Create a new attribute for the list */ + if ((attr = malloc (sizeof (DICT_ATTR))) == NULL) + { + rc_log(LOG_CRIT, "rc_read_dictionary: out of memory"); + fclose(dictfd); + return -1; + } + strcpy (attr->name, namestr); + attr->value = value | (attr_vendorspec << 16); + attr->type = type; + + if (dvend != NULL) { + attr->value = value | (dvend->vendorpec << 16); + } else { + attr->value = value | (attr_vendorspec << 16); + } + + /* Insert it into the list */ + attr->next = rh->dictionary_attributes; + rh->dictionary_attributes = attr; + } + else if (strncmp (buffer, "VALUE", 5) == 0) + { + /* Read the VALUE line */ + if (sscanf (buffer, "%63s%63s%63s%63s", dummystr, attrstr, + namestr, valstr) != 4) + { + rc_log(LOG_ERR, + "rc_read_dictionary: invalid value entry on line %d of dictionary %s", + line_no, filename); + fclose(dictfd); + return -1; + } + + /* + * Validate all entries + */ + if (strlen (attrstr) > NAME_LENGTH) + { + rc_log(LOG_ERR, + "rc_read_dictionary: invalid attribute length on line %d of dictionary %s", + line_no, filename); + fclose(dictfd); + return -1; + } + + if (strlen (namestr) > NAME_LENGTH) + { + rc_log(LOG_ERR, + "rc_read_dictionary: invalid name length on line %d of dictionary %s", + line_no, filename); + fclose(dictfd); + return -1; + } + + if (!isdigit (*valstr)) + { + rc_log(LOG_ERR, + "rc_read_dictionary: invalid value on line %d of dictionary %s", + line_no, filename); + fclose(dictfd); + return -1; + } + value = atoi (valstr); + + /* Create a new VALUE entry for the list */ + if ((dval = malloc (sizeof (DICT_VALUE))) == NULL) + { + rc_log(LOG_CRIT, "rc_read_dictionary: out of memory"); + fclose(dictfd); + return -1; + } + strcpy (dval->attrname, attrstr); + strcpy (dval->name, namestr); + dval->value = value; + + /* Insert it into the list */ + dval->next = rh->dictionary_values; + rh->dictionary_values = dval; + } + else if (strncmp (buffer, "$INCLUDE", 8) == 0) + { + /* Read the $INCLUDE line */ + if (sscanf (buffer, "%63s%63s", dummystr, namestr) != 2) + { + rc_log(LOG_ERR, + "rc_read_dictionary: invalid include entry on line %d of dictionary %s", + line_no, filename); + fclose(dictfd); + return -1; + } + ifilename = namestr; + /* Append directory if necessary */ + if (namestr[0] != '/') { + cp = strrchr(filename, '/'); + if (cp != NULL) { + ifilename = alloca(AUTH_ID_LEN); + *cp = '\0'; + snprintf(ifilename, AUTH_ID_LEN, "%s/%s", filename, namestr); + *cp = '/'; + } + } + if (rc_read_dictionary(rh, ifilename) < 0) + { + fclose(dictfd); + return -1; + } + } + else if (strncmp (buffer, "END-VENDOR", 10) == 0) + { + attr_vendorspec = 0; + } + else if (strncmp (buffer, "BEGIN-VENDOR", 12) == 0) + { + DICT_VENDOR *v; + /* Read the vendor name */ + if (sscanf (buffer+12, "%63s", dummystr) != 1) + { + rc_log(LOG_ERR, + "rc_read_dictionary: invalid Vendor-Id on line %d of dictionary %s", + line_no, filename); + fclose(dictfd); + return -1; + } + + v = rc_dict_findvend(rh, dummystr); + if (v == NULL) { + rc_log(LOG_ERR, + "rc_read_dictionary: unknown Vendor %s on line %d of dictionary %s", + dummystr, line_no, filename); + fclose(dictfd); + return -1; + } + + attr_vendorspec = v->vendorpec; + } + else if (strncmp (buffer, "VENDOR", 6) == 0) + { + /* Read the VALUE line */ + if (sscanf (buffer, "%63s%63s%63s", dummystr, attrstr, valstr) != 3) + { + rc_log(LOG_ERR, + "rc_read_dictionary: invalid Vendor-Id on line %d of dictionary %s", + line_no, filename); + fclose(dictfd); + return -1; + } + + /* Validate all entries */ + if (strlen (attrstr) > NAME_LENGTH) + { + rc_log(LOG_ERR, + "rc_read_dictionary: invalid attribute length on line %d of dictionary %s", + line_no, filename); + fclose(dictfd); + return -1; + } + + if (!isdigit (*valstr)) + { + rc_log(LOG_ERR, + "rc_read_dictionary: invalid Vendor-Id on line %d of dictionary %s", + line_no, filename); + fclose(dictfd); + return -1; + } + value = atoi (valstr); + + /* Create a new VENDOR entry for the list */ + dvend = malloc(sizeof(DICT_VENDOR)); + if (dvend == NULL) + { + rc_log(LOG_CRIT, "rc_read_dictionary: out of memory"); + fclose(dictfd); + return -1; + } + strcpy (dvend->vendorname, attrstr); + dvend->vendorpec = value; + + /* Insert it into the list */ + dvend->next = rh->dictionary_vendors; + rh->dictionary_vendors = dvend; + } + } + fclose (dictfd); + return 0; +} + +/* + * Function: rc_dict_getattr + * + * Purpose: Return the full attribute structure based on the + * attribute id number. + * + */ + +DICT_ATTR *rc_dict_getattr (rc_handle const *rh, int attribute) +{ + DICT_ATTR *attr; + + attr = rh->dictionary_attributes; + while (attr != NULL) + { + if (attr->value == attribute) + { + return attr; + } + attr = attr->next; + } + return NULL; +} + +/* + * Function: rc_dict_findattr + * + * Purpose: Return the full attribute structure based on the + * attribute name. + * + */ + +DICT_ATTR *rc_dict_findattr (rc_handle const *rh, char const *attrname) +{ + DICT_ATTR *attr; + + attr = rh->dictionary_attributes; + while (attr != NULL) + { + if (strcasecmp (attr->name, attrname) == 0) + { + return attr; + } + attr = attr->next; + } + return NULL; +} + + +/* + * Function: rc_dict_findval + * + * Purpose: Return the full value structure based on the + * value name. + * + */ + +DICT_VALUE *rc_dict_findval (rc_handle const *rh, char const *valname) +{ + DICT_VALUE *val; + + val = rh->dictionary_values; + while (val != NULL) + { + if (strcasecmp (val->name, valname) == 0) + { + return val; + } + val = val->next; + } + return NULL; +} + +/* + * Function: rc_dict_findvend + * + * Purpose: Return the full vendor structure based on the + * vendor name. + * + */ + +DICT_VENDOR * +rc_dict_findvend(rc_handle const *rh, char const *vendorname) +{ + DICT_VENDOR *vend; + + for (vend = rh->dictionary_vendors; vend != NULL; vend = vend->next) + if (strcasecmp(vend->vendorname, vendorname) == 0) + return vend; + return NULL; +} + +/* + * Function: rc_dict_getvend + * + * Purpose: Return the full vendor structure based on the + * vendor id number. + * + */ + +DICT_VENDOR * +rc_dict_getvend (rc_handle const *rh, int vendorpec) +{ + DICT_VENDOR *vend; + + for (vend = rh->dictionary_vendors; vend != NULL; vend = vend->next) + if (vend->vendorpec == vendorpec) + return vend; + return NULL; +} + +/* + * Function: dict_getval + * + * Purpose: Return the full value structure based on the + * actual value and the associated attribute name. + * + */ + +DICT_VALUE * +rc_dict_getval (rc_handle const *rh, uint32_t value, char const *attrname) +{ + DICT_VALUE *val; + + val = rh->dictionary_values; + while (val != NULL) + { + if (strcmp (val->attrname, attrname) == 0 && + val->value == value) + { + return val; + } + val = val->next; + } + return NULL; +} + +/* + * Function: rc_dict_free + * + * Purpose: Free allocated av lists + * + * Arguments: Radius Client handle + */ + +void +rc_dict_free(rc_handle *rh) +{ + DICT_ATTR *attr, *nattr; + DICT_VALUE *val, *nval; + DICT_VENDOR *vend, *nvend; + + for (attr = rh->dictionary_attributes; attr != NULL; attr = nattr) { + nattr = attr->next; + free(attr); + } + for (val = rh->dictionary_values; val != NULL; val = nval) { + nval = val->next; + free(val); + } + for (vend = rh->dictionary_vendors; vend != NULL; vend = nvend) { + nvend = vend->next; + free(vend); + } + rh->dictionary_attributes = NULL; + rh->dictionary_values = NULL; + rh->dictionary_vendors = NULL; +} diff --git a/src/plugins/vbng/lib/env.c b/src/plugins/vbng/lib/env.c new file mode 100644 index 0000000..03dccf9 --- /dev/null +++ b/src/plugins/vbng/lib/env.c @@ -0,0 +1,147 @@ +/* + * $Id: env.c,v 1.6 2007/06/21 18:07:23 cparker Exp $ + * + * Copyright (C) 1995,1996,1997 Lars Fenneberg + * + * See the file COPYRIGHT for the respective terms and conditions. + * If the file is missing contact me at lf@elemental.net + * and I'll send you a copy. + * + */ + +#include +#include +#include + +/* + * Function: rc_new_env + * + * Purpose: allocate space for a new environment + * + */ + +ENV *rc_new_env(int size) +{ + ENV *p; + + if (size < 1) + return NULL; + + if ((p = malloc(sizeof(*p))) == NULL) + return NULL; + + if ((p->env = malloc(size * sizeof(char *))) == NULL) + { + rc_log(LOG_CRIT, "rc_new_env: out of memory"); + free(p); + return NULL; + } + + p->env[0] = NULL; + + p->size = 0; + p->maxsize = size; + + return p; +} + +/* + * Function: rc_free_env + * + * Purpose: free the space used by an env structure + * + */ + +void rc_free_env(ENV *env) +{ + free(env->env); + free(env); +} + +/* + * Function: rc_add_env + * + * Purpose: add an environment entry + * + */ + +int rc_add_env(ENV *env, char const *name, char const *value) +{ + int i; + size_t len; + char *new_env; + + for (i = 0; env->env[i] != NULL; i++) + { + if (strncmp(env->env[i], name, MAX(strchr(env->env[i], '=') - env->env[i], (int)strlen(name))) == 0) + break; + } + + if (env->env[i]) + { + len = strlen(name)+strlen(value)+2; + if ((new_env = realloc(env->env[i], len)) == NULL) + return -1; + + env->env[i] = new_env; + + snprintf(env->env[i], len, "%s=%s", name, value); + } else { + if (env->size == (env->maxsize-1)) { + rc_log(LOG_CRIT, "rc_add_env: not enough space for environment (increase ENV_SIZE)"); + return -1; + } + + len = strlen(name)+strlen(value)+2; + if ((env->env[env->size] = malloc(len)) == NULL) { + rc_log(LOG_CRIT, "rc_add_env: out of memory"); + return -1; + } + + snprintf(env->env[env->size], len, "%s=%s", name, value); + + env->size++; + + env->env[env->size] = NULL; + } + + return 0; +} + +/* + * Function: rc_import_env + * + * Purpose: imports an array of null-terminated strings + * + */ + +int rc_import_env(ENV *env, char const **import) +{ + char *es; + + while (*import) + { + es = strchr(*import, '='); + + if (!es) + { + import++; + continue; + } + + /* ok, i grant thats not very clean... */ + *es = '\0'; + + if (rc_add_env(env, *import, es+1) < 0) + { + *es = '='; + return -1; + } + + *es = '='; + + import++; + } + + return 0; +} diff --git a/src/plugins/vbng/lib/ip_util.c b/src/plugins/vbng/lib/ip_util.c new file mode 100644 index 0000000..d686a59 --- /dev/null +++ b/src/plugins/vbng/lib/ip_util.c @@ -0,0 +1,390 @@ +/* + * $Id: ip_util.c,v 1.14 2010/03/17 18:57:01 aland Exp $ + * + * Copyright (C) 1995,1996,1997 Lars Fenneberg + * + * Copyright 1992 Livingston Enterprises, Inc. + * + * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan + * and Merit Network, Inc. All Rights Reserved + * + * See the file COPYRIGHT for the respective terms and conditions. + * If the file is missing contact me at lf@elemental.net + * and I'll send you a copy. + * + */ + +#include +#include +#include + +#define HOSTBUF_SIZE 1024 + +#if !defined(SA_LEN) +#define SA_LEN(sa) \ + (((sa)->sa_family == AF_INET) ? \ + sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)) +#endif + + +static __thread size_t hostbuflen=HOSTBUF_SIZE; +static __thread char *tmphostbuf=NULL; + +/* + * Function: rc_gethostbyname + * + * Purpose: threadsafe replacement for gethostbyname. + * + * Returns: NULL on failure, hostent pointer on success + */ + +struct hostent *rc_gethostbyname(char const *hostname) +{ + struct hostent *hp; +#ifdef GETHOSTBYNAME_R +#if defined (GETHOSTBYNAMERSTYLE_SYSV) || defined (GETHOSTBYNAMERSTYLE_GNU) + struct hostent hostbuf; + int res; + int herr; + + if(!tmphostbuf) tmphostbuf = malloc(hostbuflen); +#endif +#endif + +#ifdef GETHOSTBYNAME_R +#if defined (GETHOSTBYNAMERSTYLE_GNU) + while ((res = gethostbyname_r(hostname, &hostbuf, tmphostbuf, hostbuflen, &hp, &herr)) == ERANGE) + { + /* Enlarge the buffer */ + hostbuflen *= 2; + tmphostbuf = realloc(tmphostbuf, hostbuflen); + } + if(res) return NULL; +#elif defined (GETHOSTBYNAMERSTYLE_SYSV) + hp = gethostbyname_r(hostname, &hostbuf, tmphostbuf, hostbuflen, &herr); +#else + hp = gethostbyname(hostname); +#endif +#else + hp = gethostbyname(hostname); +#endif + + if (hp == NULL) { + return NULL; + } + return hp; +} + +/* + * Function: rc_gethostbyname + * + * Purpose: threadsafe replacement for gethostbyname. + * + * Returns: NULL on failure, hostent pointer on success + */ + +struct hostent *rc_gethostbyaddr(char const *addr, size_t length, int format) +{ + struct hostent *hp; +#ifdef GETHOSTBYADDR_R +#if defined (GETHOSTBYADDRRSTYLE_SYSV) || defined (GETHOSTBYADDRRSTYLE_GNU) + struct hostent hostbuf; + int res; + int herr; + + if(!tmphostbuf) tmphostbuf = malloc(hostbuflen); +#endif +#endif + +#ifdef GETHOSTBYADDR_R +#if defined (GETHOSTBYADDRRSTYLE_GNU) + while ((res = gethostbyaddr_r(addr, length, format, &hostbuf, tmphostbuf, hostbuflen, + &hp, &herr)) == ERANGE) + { + /* Enlarge the buffer */ + hostbuflen *= 2; + tmphostbuf = realloc(tmphostbuf, hostbuflen); + } + if(res) return NULL; +#elif GETHOSTBYADDRSTYLE_SYSV + hp = gethostbyaddr_r(addr, length, format, &hostbuf, tmphostbuf, hostbuflen, &herr); +#else + hp = gethostbyaddr((char *)&addr, sizeof(struct in_addr), AF_INET); +#endif +#else + hp = gethostbyaddr((char *)&addr, sizeof(struct in_addr), AF_INET); +#endif + + if (hp == NULL) { + return NULL; + } + return hp; +} + +/* + * Function: rc_get_ipaddr + * + * Purpose: return an IP address in host long notation from a host + * name or address in dot notation. + * + * Returns: 0 on failure + */ + +uint32_t rc_get_ipaddr (char const *host) +{ + struct hostent *hp; + + if (rc_good_ipaddr (host) == 0) + { + return ntohl(inet_addr (host)); + } + else if ((hp = rc_gethostbyname(host)) == NULL) + { + rc_log(LOG_ERR,"rc_get_ipaddr: couldn't resolve hostname: %s", host); + return (uint32_t)0; + } + return ntohl((*(uint32_t *) hp->h_addr)); +} + +/* + * Function: rc_good_ipaddr + * + * Purpose: check for valid IP address in standard dot notation. + * + * Returns: 0 on success, -1 when failure + * + */ + +int rc_good_ipaddr (char const *addr) +{ + int dot_count; + int digit_count; + + if (addr == NULL) + return -1; + + dot_count = 0; + digit_count = 0; + while (*addr != '\0' && *addr != ' ') + { + if (*addr == '.') + { + dot_count++; + digit_count = 0; + } + else if (!isdigit (*addr)) + { + dot_count = 5; + } + else + { + digit_count++; + if (digit_count > 3) + { + dot_count = 5; + } + } + addr++; + } + if (dot_count != 3) + { + return -1; + } + else + { + return 0; + } +} + +/* + * Function: rc_ip_hostname + * + * Purpose: Return a printable host name (or IP address in dot notation) + * for the supplied IP address. + * + */ + +char const *rc_ip_hostname (uint32_t h_ipaddr) +{ + struct hostent *hp; + uint32_t n_ipaddr = htonl (h_ipaddr); + + if ((hp = rc_gethostbyaddr ((char *) &n_ipaddr, sizeof (struct in_addr), + AF_INET)) == NULL) { + rc_log(LOG_ERR,"rc_ip_hostname: couldn't look up host by addr: %08lX", h_ipaddr); + } + + return (hp == NULL) ? "unknown" : hp->h_name; +} + +/* + * Function: rc_getport + * + * Purpose: get the port number for the supplied request type + * + */ + +unsigned short rc_getport(int type) +{ + struct servent *svp; + + if ((svp = getservbyname ((type==AUTH)?"radius":"radacct", "udp")) == NULL) + { + return (type==AUTH) ? PW_AUTH_UDP_PORT : PW_ACCT_UDP_PORT; + } else { + return ntohs ((unsigned short) svp->s_port); + } +} + +/* + * Function: rc_own_hostname + * + * Purpose: get the hostname of this machine + * + * Returns -1 on failure, 0 on success + * + */ + +int +rc_own_hostname(char *hostname, int len) +{ +#ifdef HAVE_UNAME + struct utsname uts; +#endif + +#if defined(HAVE_UNAME) + if (uname(&uts) < 0) + { + rc_log(LOG_ERR,"rc_own_hostname: couldn't get own hostname"); + return -1; + } + strncpy(hostname, uts.nodename, len); +#elif defined(HAVE_GETHOSTNAME) + if (gethostname(hostname, len) < 0) + { + rc_log(LOG_ERR,"rc_own_hostname: couldn't get own hostname"); + return -1; + } +#elif defined(HAVE_SYSINFO) + if (sysinfo(SI_HOSTNAME, hostname, len) < 0) + { + rc_log(LOG_ERR,"rc_own_hostname: couldn't get own hostname"); + return -1; + } +#else + return -1; +#endif + + return 0; +} + +/* + * Function: rc_own_ipaddress + * + * Purpose: get the IP address of this host in host order + * + * Returns: IP address on success, 0 on failure + * + */ + +uint32_t rc_own_ipaddress(rc_handle *rh) +{ + char hostname[256]; + + if (!rh->this_host_ipaddr) { + if (rc_conf_str(rh, "bindaddr") == NULL || + strcmp(rc_conf_str(rh, "bindaddr"), "*") == 0) { + if (rc_own_hostname(hostname, sizeof(hostname)) < 0) + return 0; + } else { + strncpy(hostname, rc_conf_str(rh, "bindaddr"), sizeof(hostname)); + hostname[sizeof(hostname) - 1] = '\0'; + } + if ((rh->this_host_ipaddr = rc_get_ipaddr (hostname)) == 0) { + rc_log(LOG_ERR, "rc_own_ipaddress: couldn't get own IP address"); + return 0; + } + } + + return rh->this_host_ipaddr; +} + +/* + * Function: rc_own_bind_ipaddress + * + * Purpose: get the IP address to be used as a source address + * for sending requests in host order + * + * Returns: IP address + * + */ + +uint32_t rc_own_bind_ipaddress(rc_handle *rh) +{ + char hostname[256]; + uint32_t rval; + + if (rh->this_host_bind_ipaddr != NULL) + return *rh->this_host_bind_ipaddr; + + rh->this_host_bind_ipaddr = malloc(sizeof(*rh->this_host_bind_ipaddr)); + if (rh->this_host_bind_ipaddr == NULL) + rc_log(LOG_CRIT, "rc_own_bind_ipaddress: out of memory"); + if (rc_conf_str(rh, "bindaddr") == NULL || + strcmp(rc_conf_str(rh, "bindaddr"), "*") == 0) { + rval = INADDR_ANY; + } else { + strncpy(hostname, rc_conf_str(rh, "bindaddr"), sizeof(hostname)); + hostname[sizeof(hostname) - 1] = '\0'; + if ((rval = rc_get_ipaddr (hostname)) == 0) { + rc_log(LOG_ERR, "rc_own_ipaddress: couldn't get IP address from bindaddr"); + rval = INADDR_ANY; + } + } + if (rh->this_host_bind_ipaddr != NULL) + *rh->this_host_bind_ipaddr = rval; + + return rval; +} + +/* + * Function: rc_get_srcaddr + * + * Purpose: given remote address find local address which the + * system will use as a source address for sending + * datagrams to that remote address + * + * Returns: 0 in success, -1 on failure, address is filled into + * the first argument. + * + */ +int +rc_get_srcaddr(struct sockaddr *lia, struct sockaddr *ria) +{ + int temp_sock; + socklen_t namelen; + + temp_sock = socket(ria->sa_family, SOCK_DGRAM, 0); + if (temp_sock == -1) { + rc_log(LOG_ERR, "rc_get_srcaddr: socket: %s", strerror(errno)); + return -1; + } + + if (connect(temp_sock, ria, SA_LEN(ria)) != 0) { + rc_log(LOG_ERR, "rc_get_srcaddr: connect: %s", + strerror(errno)); + close(temp_sock); + return -1; + } + + namelen = SA_LEN(ria); + if (getsockname(temp_sock, lia, &namelen) != 0) { + rc_log(LOG_ERR, "rc_get_srcaddr: getsockname: %s", + strerror(errno)); + close(temp_sock); + return -1; + } + + close(temp_sock); + return 0; +} diff --git a/src/plugins/vbng/lib/log.c b/src/plugins/vbng/lib/log.c new file mode 100644 index 0000000..09b01a2 --- /dev/null +++ b/src/plugins/vbng/lib/log.c @@ -0,0 +1,57 @@ +/* + * $Id: log.c,v 1.5 2007/06/21 18:07:23 cparker Exp $ + * + * Copyright (C) 1995,1996,1997 Lars Fenneberg + * + * See the file COPYRIGHT for the respective terms and conditions. + * If the file is missing contact me at lf@elemental.net + * and I'll send you a copy. + * + */ + +#include +#include +#include + +/* + * Function: rc_openlog + * + * Purpose: open log + * + * Arguments: identification string + * + * Returns: nothing + * + */ + +void rc_openlog(char const *ident) +{ +#ifndef _MSC_VER /* TODO: Fix me */ + openlog(ident, LOG_PID, RC_LOG_FACILITY); +#endif +} + +/* + * Function: rc_log + * + * Purpose: log information + * + * Arguments: priority (just like syslog), rest like printf + * + * Returns: nothing + * + */ + +void rc_log(int prio, char const *format, ...) +{ + char buff[1024]; + va_list ap; + + va_start(ap,format); + vsnprintf(buff, sizeof(buff), format, ap); + va_end(ap); + +#ifndef _MSC_VER /* TODO: Fix me */ + syslog(prio, "%s", buff); +#endif +} diff --git a/src/plugins/vbng/lib/md5.c b/src/plugins/vbng/lib/md5.c new file mode 100644 index 0000000..2344fb9 --- /dev/null +++ b/src/plugins/vbng/lib/md5.c @@ -0,0 +1,251 @@ +#include "md5.h" + +/* The below was retrieved from + * http://www.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/crypto/md5.c?rev=1.1 + * with the following changes: + * #includes commented out. + * Support context->count as uint32_t[2] instead of uint64_t + * u_int* to uint* + */ + +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ + +/*#include */ +/*#include */ +/*#include */ + +#define PUT_64BIT_LE(cp, value) do { \ + (cp)[7] = (value)[1] >> 24; \ + (cp)[6] = (value)[1] >> 16; \ + (cp)[5] = (value)[1] >> 8; \ + (cp)[4] = (value)[1]; \ + (cp)[3] = (value)[0] >> 24; \ + (cp)[2] = (value)[0] >> 16; \ + (cp)[1] = (value)[0] >> 8; \ + (cp)[0] = (value)[0]; } while (0) + +#define PUT_32BIT_LE(cp, value) do { \ + (cp)[3] = (value) >> 24; \ + (cp)[2] = (value) >> 16; \ + (cp)[1] = (value) >> 8; \ + (cp)[0] = (value); } while (0) + +static uint8_t PADDING[MD5_BLOCK_LENGTH] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void +MD5Init(MD5_CTX *ctx) +{ + ctx->count[0] = 0; + ctx->count[1] = 0; + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xefcdab89; + ctx->state[2] = 0x98badcfe; + ctx->state[3] = 0x10325476; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void +MD5Update(MD5_CTX *ctx, uint8_t const *input, size_t len) +{ + size_t have, need; + + /* Check how many bytes we already have and how many more we need. */ + have = (size_t)((ctx->count[0] >> 3) & (MD5_BLOCK_LENGTH - 1)); + need = MD5_BLOCK_LENGTH - have; + + /* Update bitcount */ +/* ctx->count += (uint64_t)len << 3;*/ + if ((ctx->count[0] += ((uint32_t)len << 3)) < (uint32_t)len) { + /* Overflowed ctx->count[0] */ + ctx->count[1]++; + } + ctx->count[1] += ((uint32_t)len >> 29); + + + + if (len >= need) { + if (have != 0) { + memcpy(ctx->buffer + have, input, need); + MD5Transform(ctx->state, ctx->buffer); + input += need; + len -= need; + have = 0; + } + + /* Process data in MD5_BLOCK_LENGTH-byte chunks. */ + while (len >= MD5_BLOCK_LENGTH) { + MD5Transform(ctx->state, input); + input += MD5_BLOCK_LENGTH; + len -= MD5_BLOCK_LENGTH; + } + } + + /* Handle any remaining bytes of data. */ + if (len != 0) + memcpy(ctx->buffer + have, input, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void +MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx) +{ + uint8_t count[8]; + size_t padlen; + int i; + + /* Convert count to 8 bytes in little endian order. */ + PUT_64BIT_LE(count, ctx->count); + + /* Pad out to 56 mod 64. */ + padlen = MD5_BLOCK_LENGTH - + ((ctx->count[0] >> 3) & (MD5_BLOCK_LENGTH - 1)); + if (padlen < 1 + 8) + padlen += MD5_BLOCK_LENGTH; + MD5Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */ + MD5Update(ctx, count, 8); + + if (digest != NULL) { + for (i = 0; i < 4; i++) + PUT_32BIT_LE(digest + i * 4, ctx->state[i]); + } + memset(ctx, 0, sizeof(*ctx)); /* in case it's sensitive */ +} + + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +void +MD5Transform(uint32_t state[4], uint8_t const block[MD5_BLOCK_LENGTH]) +{ + uint32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4]; + + for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) { + in[a] = (uint32_t)( + (uint32_t)(block[a * 4 + 0]) | + (uint32_t)(block[a * 4 + 1]) << 8 | + (uint32_t)(block[a * 4 + 2]) << 16 | + (uint32_t)(block[a * 4 + 3]) << 24); + } + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + + MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2 ] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7 ] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5 ] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3 ] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1 ] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8 ] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6 ] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4 ] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2 ] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9 ] + 0xeb86d391, 21); + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; +} diff --git a/src/plugins/vbng/lib/md5.h b/src/plugins/vbng/lib/md5.h new file mode 100644 index 0000000..fcbaf91 --- /dev/null +++ b/src/plugins/vbng/lib/md5.h @@ -0,0 +1,86 @@ +/* + * md5.h Structures and prototypes for md5. + * + * Version: $Id: md5.h,v 1.2 2007/06/21 18:07:24 cparker Exp $ + * License: BSD, but largely derived from a public domain source. + * + */ + +#ifndef _RCRAD_MD5_H +#define _RCRAD_MD5_H + +#include "config.h" + +#ifdef HAVE_NETTLE + +#include + +#else + +#ifdef HAVE_INTTYPES_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_STDINT_H +#include +#endif + +#include +/* + * FreeRADIUS Client defines to ensure globally unique MD5 function names, + * so that we don't pick up vendor-specific broken MD5 libraries. + */ +#define MD5_CTX librad_MD5_CTX +#define MD5Init librad_MD5Init +#define MD5Update librad_MD5Update +#define MD5Final librad_MD5Final +#define MD5Transform librad_MD5Transform + +/* The below was retrieved from + * http://www.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/crypto/md5.h?rev=1.1 + * With the following changes: uint64_t => uint32_t[2] + * Commented out #include + * Commented out the __BEGIN and __END _DECLS, and the __attributes. + */ + +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + */ + +#define MD5_BLOCK_LENGTH 64 +#define MD5_DIGEST_LENGTH 16 + +typedef struct MD5Context { + uint32_t state[4]; /* state */ + uint32_t count[2]; /* number of bits, mod 2^64 */ + uint8_t buffer[MD5_BLOCK_LENGTH]; /* input buffer */ +} MD5_CTX; + +/* include */ + +/* __BEGIN_DECLS */ +void MD5Init(MD5_CTX *); +void MD5Update(MD5_CTX *, uint8_t const *, size_t) +/* __attribute__((__bounded__(__string__,2,3)))*/; +void MD5Final(uint8_t [MD5_DIGEST_LENGTH], MD5_CTX *) +/* __attribute__((__bounded__(__minbytes__,1,MD5_DIGEST_LENGTH)))*/; +void MD5Transform(uint32_t [4], uint8_t const [MD5_BLOCK_LENGTH]) +/* __attribute__((__bounded__(__minbytes__,1,4)))*/ +/* __attribute__((__bounded__(__minbytes__,2,MD5_BLOCK_LENGTH)))*/; +/* __END_DECLS */ + +#endif /* HAVE_NETTLE */ + +#endif /* _RCRAD_MD5_H */ diff --git a/src/plugins/vbng/lib/options.h b/src/plugins/vbng/lib/options.h new file mode 100644 index 0000000..05b66df --- /dev/null +++ b/src/plugins/vbng/lib/options.h @@ -0,0 +1,57 @@ +/* + * $Id: options.h,v 1.6 2008/03/05 16:35:20 cparker Exp $ + * + * Copyright (C) 1996 Lars Fenneberg + * + * See the file COPYRIGHT for the respective terms and conditions. + * If the file is missing contact me at lf@elemental.net + * and I'll send you a copy. + * + */ + +#define OPTION_LEN 64 + +/* ids for different option types */ +#define OT_STR (1<<0) /* string */ +#define OT_INT (1<<1) /* integer */ +#define OT_SRV (1<<2) /* server list */ +#define OT_AUO (1<<3) /* authentication order */ + +#define OT_ANY ((unsigned int)~0) /* used internally */ + +/* status types */ +#define ST_UNDEF (1<<0) /* option is undefined */ + +typedef struct _option { + char name[OPTION_LEN]; /* name of the option */ + int type, status; /* type and status */ + void *val; /* pointer to option value */ +} OPTION; + +static OPTION config_options_default[] = { +/* internally used options */ +{"config_file", OT_STR, ST_UNDEF, NULL}, +/* General options */ +{"auth_order", OT_AUO, ST_UNDEF, NULL}, +{"login_tries", OT_INT, ST_UNDEF, NULL}, +{"login_timeout", OT_INT, ST_UNDEF, NULL}, +{"nologin", OT_STR, ST_UNDEF, NULL}, +{"issue", OT_STR, ST_UNDEF, NULL}, +/* RADIUS specific options */ +{"authserver", OT_SRV, ST_UNDEF, NULL}, +{"acctserver", OT_SRV, ST_UNDEF, NULL}, +{"servers", OT_STR, ST_UNDEF, NULL}, +{"dictionary", OT_STR, ST_UNDEF, NULL}, +{"login_radius", OT_STR, ST_UNDEF, NULL}, +{"seqfile", OT_STR, ST_UNDEF, NULL}, +{"mapfile", OT_STR, ST_UNDEF, NULL}, +{"default_realm", OT_STR, ST_UNDEF, NULL}, +{"radius_timeout", OT_INT, ST_UNDEF, NULL}, +{"radius_retries", OT_INT, ST_UNDEF, NULL}, +{"radius_deadtime", OT_INT, ST_UNDEF, NULL}, +{"bindaddr", OT_STR, ST_UNDEF, NULL}, +/* local options */ +{"login_local", OT_STR, ST_UNDEF, NULL}, +}; + +#define NUM_OPTIONS ((sizeof(config_options_default))/(sizeof(config_options_default[0]))) diff --git a/src/plugins/vbng/lib/rc-md5.c b/src/plugins/vbng/lib/rc-md5.c new file mode 100644 index 0000000..be9fbcb --- /dev/null +++ b/src/plugins/vbng/lib/rc-md5.c @@ -0,0 +1,24 @@ +/* MD5 message-digest algorithm */ + +/* This file is licensed under the BSD License, but is largely derived from + * public domain source code + */ + +/* + * FORCE MD5 TO USE OUR MD5 HEADER FILE! + * + * If we don't do this, it might pick up the systems broken MD5. + * - Alan DeKok + */ +#include "rc-md5.h" + +void rc_md5_calc(unsigned char *output, unsigned char const *input, + size_t inlen) +{ + MD5_CTX context; + + MD5Init(&context); + MD5Update(&context, input, inlen); + MD5Final(output, &context); +} + diff --git a/src/plugins/vbng/lib/rc-md5.h b/src/plugins/vbng/lib/rc-md5.h new file mode 100644 index 0000000..a30f16d --- /dev/null +++ b/src/plugins/vbng/lib/rc-md5.h @@ -0,0 +1,27 @@ +/* + * md5.h Structures and prototypes for md5. + * + * Version: $Id: md5.h,v 1.2 2007/06/21 18:07:24 cparker Exp $ + * License: BSD + * + */ + +#ifndef _RC_MD5_H +#define _RC_MD5_H + +#include "config.h" + +#ifdef HAVE_NETTLE + +#include + +#else + +#include "md5.h" + +#endif /* HAVE_NETTLE */ + +void rc_md5_calc(unsigned char *output, unsigned char const *input, + size_t inputlen); + +#endif /* _RC_MD5_H */ diff --git a/src/plugins/vbng/lib/sendserver.c b/src/plugins/vbng/lib/sendserver.c new file mode 100644 index 0000000..bfdd9a2 --- /dev/null +++ b/src/plugins/vbng/lib/sendserver.c @@ -0,0 +1,631 @@ +/* + * $Id: sendserver.c,v 1.30 2010/06/15 09:22:52 aland Exp $ + * + * Copyright (C) 1995,1996,1997 Lars Fenneberg + * + * Copyright 1992 Livingston Enterprises, Inc. + * + * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan + * and Merit Network, Inc. All Rights Reserved + * + * See the file COPYRIGHT for the respective terms and conditions. + * If the file is missing contact me at lf@elemental.net + * and I'll send you a copy. + * + */ + +#include + +#include +#include +#include +#include + +#define SA(p) ((struct sockaddr *)(p)) + +static void rc_random_vector (unsigned char *); +static int rc_check_reply (AUTH_HDR *, int, char const *, unsigned char const *, unsigned char); + +/* + * Function: rc_pack_list + * + * Purpose: Packs an attribute value pair list into a buffer. + * + * Returns: Number of octets packed. + * + */ + +static int rc_pack_list (VALUE_PAIR *vp, char *secret, AUTH_HDR *auth) +{ + int length, i, pc, padded_length; + int total_length = 0; + size_t secretlen; + uint32_t lvalue, vendor; + unsigned char passbuf[MAX(AUTH_PASS_LEN, CHAP_VALUE_LENGTH)]; + unsigned char md5buf[256]; + unsigned char *buf, *vector, *vsa_length_ptr; + + buf = auth->data; + + while (vp != NULL) + { + vsa_length_ptr = NULL; + if (VENDOR(vp->attribute) != 0) { + *buf++ = PW_VENDOR_SPECIFIC; + vsa_length_ptr = buf; + *buf++ = 6; + vendor = htonl(VENDOR(vp->attribute)); + memcpy(buf, &vendor, sizeof(uint32_t)); + buf += 4; + total_length += 6; + } + *buf++ = (vp->attribute & 0xff); + + switch (vp->attribute) + { + case PW_USER_PASSWORD: + + /* Encrypt the password */ + + /* Chop off password at AUTH_PASS_LEN */ + length = vp->lvalue; + if (length > AUTH_PASS_LEN) + length = AUTH_PASS_LEN; + + /* Calculate the padded length */ + padded_length = (length+(AUTH_VECTOR_LEN-1)) & ~(AUTH_VECTOR_LEN-1); + + /* Record the attribute length */ + *buf++ = padded_length + 2; + if (vsa_length_ptr != NULL) *vsa_length_ptr += padded_length + 2; + + /* Pad the password with zeros */ + memset ((char *) passbuf, '\0', AUTH_PASS_LEN); + memcpy ((char *) passbuf, vp->strvalue, (size_t) length); + + secretlen = strlen (secret); + vector = (unsigned char *)auth->vector; + for(i = 0; i < padded_length; i += AUTH_VECTOR_LEN) + { + /* Calculate the MD5 digest*/ + strcpy ((char *) md5buf, secret); + memcpy ((char *) md5buf + secretlen, vector, + AUTH_VECTOR_LEN); + rc_md5_calc (buf, md5buf, secretlen + AUTH_VECTOR_LEN); + + /* Remeber the start of the digest */ + vector = buf; + + /* Xor the password into the MD5 digest */ + for (pc = i; pc < (i + AUTH_VECTOR_LEN); pc++) + { + *buf++ ^= passbuf[pc]; + } + } + + total_length += padded_length + 2; + + break; +#if 0 + case PW_CHAP_PASSWORD: + + *buf++ = CHAP_VALUE_LENGTH + 2; + if (vsa_length_ptr != NULL) *vsa_length_ptr += CHAP_VALUE_LENGTH + 2; + + /* Encrypt the Password */ + length = vp->lvalue; + if (length > CHAP_VALUE_LENGTH) + { + length = CHAP_VALUE_LENGTH; + } + memset ((char *) passbuf, '\0', CHAP_VALUE_LENGTH); + memcpy ((char *) passbuf, vp->strvalue, (size_t) length); + + /* Calculate the MD5 Digest */ + secretlen = strlen (secret); + strcpy ((char *) md5buf, secret); + memcpy ((char *) md5buf + secretlen, (char *) auth->vector, + AUTH_VECTOR_LEN); + rc_md5_calc (buf, md5buf, secretlen + AUTH_VECTOR_LEN); + + /* Xor the password into the MD5 digest */ + for (i = 0; i < CHAP_VALUE_LENGTH; i++) + { + *buf++ ^= passbuf[i]; + } + total_length += CHAP_VALUE_LENGTH + 2; + + break; +#endif + default: + switch (vp->type) + { + case PW_TYPE_STRING: + length = vp->lvalue; + *buf++ = length + 2; + if (vsa_length_ptr != NULL) *vsa_length_ptr += length + 2; + memcpy (buf, vp->strvalue, (size_t) length); + buf += length; + total_length += length + 2; + break; + + case PW_TYPE_IPV6ADDR: + length = 16; + if (vsa_length_ptr != NULL) *vsa_length_ptr += length + 2; + memcpy (buf, vp->strvalue, (size_t) length); + buf += length; + total_length += length + 2; + break; + + case PW_TYPE_IPV6PREFIX: + length = vp->lvalue; + if (vsa_length_ptr != NULL) *vsa_length_ptr += length + 2; + memcpy (buf, vp->strvalue, (size_t) length); + buf += length; + total_length += length + 2; + break; + + case PW_TYPE_INTEGER: + case PW_TYPE_IPADDR: + case PW_TYPE_DATE: + *buf++ = sizeof (uint32_t) + 2; + if (vsa_length_ptr != NULL) *vsa_length_ptr += sizeof(uint32_t) + 2; + lvalue = htonl (vp->lvalue); + memcpy (buf, (char *) &lvalue, sizeof (uint32_t)); + buf += sizeof (uint32_t); + total_length += sizeof (uint32_t) + 2; + break; + + default: + break; + } + break; + } + vp = vp->next; + } + return total_length; +} + +/* Function strappend + * + * Purpose: appends a string to the provided buffer + */ +static void strappend(char *dest, unsigned max_size, int *pos, const char *src) +{ + unsigned len = strlen(src) + 1; + + if (*pos == -1) + return; + + if (len + *pos > max_size) { + *pos = -1; + return; + } + + memcpy(&dest[*pos], src, len); + *pos += len-1; + return; +} + +/* + * Function: rc_send_server + * + * Purpose: send a request to a RADIUS server and wait for the reply + * + */ + +int rc_send_server (rc_handle *rh, SEND_DATA *data, char *msg) +{ + int sockfd; + struct sockaddr_in sinlocal; + struct sockaddr_in sinremote; + AUTH_HDR *auth, *recv_auth; + uint32_t auth_ipaddr, nas_ipaddr; + char *server_name; /* Name of server to query */ + socklen_t salen; + int result = 0; + int total_length; + int length, pos; + int retry_max; + size_t secretlen; + char secret[MAX_SECRET_LENGTH + 1]; + unsigned char vector[AUTH_VECTOR_LEN]; + char recv_buffer[BUFFER_LEN]; + char send_buffer[BUFFER_LEN]; + int retries; + VALUE_PAIR *vp; + struct pollfd pfd; + double start_time, timeout; + + server_name = data->server; + if (server_name == NULL || server_name[0] == '\0') + return ERROR_RC; + + if ((vp = rc_avpair_get(data->send_pairs, PW_SERVICE_TYPE, 0)) && \ + (vp->lvalue == PW_ADMINISTRATIVE)) + { + strcpy(secret, MGMT_POLL_SECRET); + if ((auth_ipaddr = rc_get_ipaddr(server_name)) == 0) + return ERROR_RC; + } + else + { + if(data->secret != NULL) + { + strncpy(secret, data->secret, MAX_SECRET_LENGTH); + } + /* + else + { + */ + if (rc_find_server (rh, server_name, &auth_ipaddr, secret) != 0) + { + rc_log(LOG_ERR, "rc_send_server: unable to find server: %s", server_name); + return ERROR_RC; + } + /*}*/ + } + + DEBUG(LOG_ERR, "DEBUG: rc_send_server: creating socket to: %s", server_name); + + sockfd = socket (AF_INET, SOCK_DGRAM, 0); + if (sockfd < 0) + { + memset (secret, '\0', sizeof (secret)); + rc_log(LOG_ERR, "rc_send_server: socket: %s", strerror(errno)); + return ERROR_RC; + } + + memset((char *)&sinlocal, '\0', sizeof(sinlocal)); + sinlocal.sin_family = AF_INET; + sinlocal.sin_addr.s_addr = htonl(rc_own_bind_ipaddress(rh)); + sinlocal.sin_port = htons((unsigned short) 0); + if (bind(sockfd, SA(&sinlocal), sizeof(sinlocal)) < 0) + { + close (sockfd); + memset (secret, '\0', sizeof (secret)); + rc_log(LOG_ERR, "rc_send_server: bind: %s: %s", server_name, strerror(errno)); + return ERROR_RC; + } + + retry_max = data->retries; /* Max. numbers to try for reply */ + retries = 0; /* Init retry cnt for blocking call */ + + memset ((char *)&sinremote, '\0', sizeof(sinremote)); + sinremote.sin_family = AF_INET; + sinremote.sin_addr.s_addr = htonl (auth_ipaddr); + sinremote.sin_port = htons ((unsigned short) data->svc_port); + + /* + * Fill in NAS-IP-Address (if needed) + */ + if (rc_avpair_get(data->send_pairs, PW_NAS_IP_ADDRESS, 0) == NULL) { + if (sinlocal.sin_addr.s_addr == htonl(INADDR_ANY)) { + if (rc_get_srcaddr(SA(&sinlocal), SA(&sinremote)) != 0) { + close (sockfd); + memset (secret, '\0', sizeof (secret)); + return ERROR_RC; + } + } + nas_ipaddr = ntohl(sinlocal.sin_addr.s_addr); + rc_avpair_add(rh, &(data->send_pairs), PW_NAS_IP_ADDRESS, + &nas_ipaddr, 0, 0); + } + + /* Build a request */ + auth = (AUTH_HDR *) send_buffer; + auth->code = data->code; + auth->id = data->seq_nbr; + + if (data->code == PW_ACCOUNTING_REQUEST) + { + total_length = rc_pack_list(data->send_pairs, secret, auth) + AUTH_HDR_LEN; + + auth->length = htons ((unsigned short) total_length); + + memset((char *) auth->vector, 0, AUTH_VECTOR_LEN); + secretlen = strlen (secret); + memcpy ((char *) auth + total_length, secret, secretlen); + rc_md5_calc (vector, (unsigned char *) auth, total_length + secretlen); + memcpy ((char *) auth->vector, (char *) vector, AUTH_VECTOR_LEN); + } + else + { + rc_random_vector (vector); + memcpy ((char *) auth->vector, (char *) vector, AUTH_VECTOR_LEN); + + total_length = rc_pack_list(data->send_pairs, secret, auth) + AUTH_HDR_LEN; + + auth->length = htons ((unsigned short) total_length); + } + + DEBUG(LOG_ERR, "DEBUG: local %s : 0, remote %s : %u\n", + inet_ntoa(sinlocal.sin_addr), + inet_ntoa(sinremote.sin_addr), data->svc_port); + + for (;;) + { + sendto (sockfd, (char *) auth, (unsigned int) total_length, (int) 0, + SA(&sinremote), sizeof (struct sockaddr_in)); + + pfd.fd = sockfd; + pfd.events = POLLIN; + pfd.revents = 0; + start_time = rc_getctime(); + for (timeout = data->timeout; timeout > 0; + timeout -= rc_getctime() - start_time) { + result = poll(&pfd, 1, timeout * 1000); + if (result != -1 || errno != EINTR) + break; + } + if (result == -1) + { + rc_log(LOG_ERR, "rc_send_server: poll: %s", strerror(errno)); + memset (secret, '\0', sizeof (secret)); + close (sockfd); + return ERROR_RC; + } + if (result == 1 && (pfd.revents & POLLIN) != 0) + break; + + /* + * Timed out waiting for response. Retry "retry_max" times + * before giving up. If retry_max = 0, don't retry at all. + */ + if (retries++ >= retry_max) + { + rc_log(LOG_ERR, + "rc_send_server: no reply from RADIUS server %s:%u, %s", + rc_ip_hostname (auth_ipaddr), data->svc_port, inet_ntoa(sinremote.sin_addr)); + close (sockfd); + memset (secret, '\0', sizeof (secret)); + return TIMEOUT_RC; + } + } + salen = sizeof(sinremote); + length = recvfrom (sockfd, (char *) recv_buffer, + (int) sizeof (recv_buffer), + (int) 0, SA(&sinremote), &salen); + + if (length <= 0) + { + rc_log(LOG_ERR, "rc_send_server: recvfrom: %s:%d: %s", server_name,\ + data->svc_port, strerror(errno)); + close (sockfd); + memset (secret, '\0', sizeof (secret)); + return ERROR_RC; + } + + recv_auth = (AUTH_HDR *)recv_buffer; + + if (length < AUTH_HDR_LEN || length < ntohs(recv_auth->length)) { + rc_log(LOG_ERR, "rc_send_server: recvfrom: %s:%d: reply is too short", + server_name, data->svc_port); + close(sockfd); + memset(secret, '\0', sizeof(secret)); + return ERROR_RC; + } + + result = rc_check_reply (recv_auth, BUFFER_LEN, secret, vector, data->seq_nbr); + + length = ntohs(recv_auth->length) - AUTH_HDR_LEN; + if (length > 0) { + data->receive_pairs = rc_avpair_gen(rh, NULL, recv_auth->data, + length, 0); + } else { + data->receive_pairs = NULL; + } + + close (sockfd); + memset (secret, '\0', sizeof (secret)); + + if (result != OK_RC) return result; + + if (msg) { + *msg = '\0'; + pos = 0; + vp = data->receive_pairs; + while (vp) + { + if ((vp = rc_avpair_get(vp, PW_REPLY_MESSAGE, 0))) + { + strappend(msg, PW_MAX_MSG_SIZE, &pos, vp->strvalue); + strappend(msg, PW_MAX_MSG_SIZE, &pos, "\n"); + vp = vp->next; + } + } + } + + if ((recv_auth->code == PW_ACCESS_ACCEPT) || + (recv_auth->code == PW_PASSWORD_ACK) || + (recv_auth->code == PW_ACCOUNTING_RESPONSE)) + { + result = OK_RC; + } + else if ((recv_auth->code == PW_ACCESS_REJECT) || + (recv_auth->code == PW_PASSWORD_REJECT)) + { + result = REJECT_RC; + } + else + { + result = BADRESP_RC; + } + + return result; +} + +/* + * Function: rc_check_reply + * + * Purpose: verify items in returned packet. + * + * Returns: OK_RC -- upon success, + * BADRESP_RC -- if anything looks funny. + * + */ + +static int rc_check_reply (AUTH_HDR *auth, int bufferlen, char const *secret, unsigned char const *vector, uint8_t seq_nbr) +{ + int secretlen; + int totallen; + unsigned char calc_digest[AUTH_VECTOR_LEN]; + unsigned char reply_digest[AUTH_VECTOR_LEN]; +#ifdef DIGEST_DEBUG + uint8_t *ptr; +#endif + + totallen = ntohs (auth->length); + secretlen = (int)strlen (secret); + + /* Do sanity checks on packet length */ + if ((totallen < 20) || (totallen > 4096)) + { + rc_log(LOG_ERR, "rc_check_reply: received RADIUS server response with invalid length"); + return BADRESP_RC; + } + + /* Verify buffer space, should never trigger with current buffer size and check above */ + if ((totallen + secretlen) > bufferlen) + { + rc_log(LOG_ERR, "rc_check_reply: not enough buffer space to verify RADIUS server response"); + return BADRESP_RC; + } + + /* Verify that id (seq. number) matches what we sent */ + if (auth->id != seq_nbr) + { + rc_log(LOG_ERR, "rc_check_reply: received non-matching id in RADIUS server response"); + return BADRESP_RC; + } + + /* Verify the reply digest */ + memcpy ((char *) reply_digest, (char *) auth->vector, AUTH_VECTOR_LEN); + memcpy ((char *) auth->vector, (char *) vector, AUTH_VECTOR_LEN); + memcpy ((char *) auth + totallen, secret, secretlen); +#ifdef DIGEST_DEBUG + rc_log(LOG_ERR, "Calculating digest on:"); + for (ptr = (u_char *)auth; ptr < ((u_char *)auth) + totallen + secretlen; ptr += 32) { + char buf[65]; + int i; + + buf[0] = '\0'; + for (i = 0; i < 32; i++) { + if (ptr + i >= ((u_char *)auth) + totallen + secretlen) + break; + sprintf(buf + i * 2, "%.2X", ptr[i]); + } + rc_log(LOG_ERR, " %s", buf); + } +#endif + rc_md5_calc (calc_digest, (unsigned char *) auth, totallen + secretlen); +#ifdef DIGEST_DEBUG + rc_log(LOG_ERR, "Calculated digest is:"); + for (ptr = (u_char *)calc_digest; ptr < ((u_char *)calc_digest) + 16; ptr += 32) { + char buf[65]; + int i; + + buf[0] = '\0'; + for (i = 0; i < 32; i++) { + if (ptr + i >= ((u_char *)calc_digest) + 16) + break; + sprintf(buf + i * 2, "%.2X", ptr[i]); + } + rc_log(LOG_ERR, " %s", buf); + } + rc_log(LOG_ERR, "Reply digest is:"); + for (ptr = (u_char *)reply_digest; ptr < ((u_char *)reply_digest) + 16; ptr += 32) { + char buf[65]; + int i; + + buf[0] = '\0'; + for (i = 0; i < 32; i++) { + if (ptr + i >= ((u_char *)reply_digest) + 16) + break; + sprintf(buf + i * 2, "%.2X", ptr[i]); + } + rc_log(LOG_ERR, " %s", buf); + } +#endif + + if (memcmp ((char *) reply_digest, (char *) calc_digest, + AUTH_VECTOR_LEN) != 0) + { +#ifdef RADIUS_116 + /* the original Livingston radiusd v1.16 seems to have + a bug in digest calculation with accounting requests, + authentication request are ok. i looked at the code + but couldn't find any bugs. any help to get this + kludge out are welcome. preferably i want to + reproduce the calculation bug here to be compatible + to stock Livingston radiusd v1.16. -lf, 03/14/96 + */ + if (auth->code == PW_ACCOUNTING_RESPONSE) + return OK_RC; +#endif + rc_log(LOG_ERR, "rc_check_reply: received invalid reply digest from RADIUS server"); + return BADRESP_RC; + } + + return OK_RC; + +} + +/* + * Function: rc_random_vector + * + * Purpose: generates a random vector of AUTH_VECTOR_LEN octets. + * + * Returns: the vector (call by reference) + * + */ + +static void rc_random_vector (unsigned char *vector) +{ + int randno; + int i; +#if defined(HAVE_GETENTROPY) + if (getentropy(vector, AUTH_VECTOR_LEN) >= 0) { + return; + } /* else fall through */ +#elif defined(HAVE_DEV_URANDOM) + int fd; + +/* well, I added this to increase the security for user passwords. + we use /dev/urandom here, as /dev/random might block and we don't + need that much randomness. BTW, great idea, Ted! -lf, 03/18/95 */ + + if ((fd = open(_PATH_DEV_URANDOM, O_RDONLY)) >= 0) + { + unsigned char *pos; + int readcount; + + i = AUTH_VECTOR_LEN; + pos = vector; + while (i > 0) + { + readcount = read(fd, (char *)pos, i); + if (readcount >= 0) { + pos += readcount; + i -= readcount; + } else { + if (errno != EINTR && errno != EAGAIN) + goto fallback; + } + } + + close(fd); + return; + } /* else fall through */ +#endif + fallback: + for (i = 0; i < AUTH_VECTOR_LEN;) + { + randno = random (); + memcpy ((char *) vector, (char *) &randno, sizeof (int)); + vector += sizeof (int); + i += sizeof (int); + } + + return; +} diff --git a/src/plugins/vbng/lib/util.c b/src/plugins/vbng/lib/util.c new file mode 100644 index 0000000..aa7c057 --- /dev/null +++ b/src/plugins/vbng/lib/util.c @@ -0,0 +1,347 @@ +/* + * $Id: util.c,v 1.10 2010/02/04 10:31:41 aland Exp $ + * + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * + * Copyright (C) 1995,1996,1997 Lars Fenneberg + * + * Copyright 1992 Livingston Enterprises, Inc. + * + * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan + * and Merit Network, Inc. All Rights Reserved + * + * See the file COPYRIGHT for the respective terms and conditions. + * If the file is missing contact me at lf@elemental.net + * and I'll send you a copy. + * + */ + +#include + +#include +#include +#include + +#define RC_BUFSIZ 1024 + +/* + * Function: rc_str2tm + * + * Purpose: Turns printable string into correct tm struct entries. + * + */ + +static char const * months[] = + { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; + +void rc_str2tm (char const *valstr, struct tm *tm) +{ + int i; + + /* Get the month */ + for (i = 0; i < 12; i++) + { + if (strncmp (months[i], valstr, 3) == 0) + { + tm->tm_mon = i; + i = 13; + } + } + + /* Get the Day */ + tm->tm_mday = atoi (&valstr[4]); + + /* Now the year */ + tm->tm_year = atoi (&valstr[7]) - 1900; +} + +/* + * Function: rc_getifname + * + * Purpose: get the network interface name associated with this tty + * + */ + +char *rc_getifname(rc_handle *rh, char const *tty) +{ +#if defined(BSD4_4) || defined(linux) + int fd; + + if ((fd = open(tty, O_RDWR|O_NDELAY)) < 0) { + rc_log(LOG_ERR, "rc_getifname: can't open %s: %s", tty, strerror(errno)); + return NULL; + } +#endif + +#ifdef BSD4_4 + strcpy(rh->ifname,ttyname(fd)); + if (strlen(rh->ifname) < 1) { + rc_log(LOG_ERR, "rc_getifname: can't get attached interface of %s: %s", tty, strerror(errno)); + close(fd); + return NULL; + } +#elif linux + if (ioctl(fd, SIOCGIFNAME, rh->ifname) < 0) { + rc_log(LOG_ERR, "rc_getifname: can't ioctl %s: %s", tty, strerror(errno)); + close(fd); + return NULL; + } +#else + return NULL; +#endif + +#if defined(BSD4_4) || defined(linux) + close(fd); + return rh->ifname; +#endif +} + +/* + * Function: rc_getstr + * + * Purpose: Reads in a string from the user (with or witout echo) + * + */ +#ifndef _MSC_VER +char *rc_getstr (rc_handle *rh, char const *prompt, int do_echo) +{ + int in, out; + char *p; + struct termios term_old, term_new; + int is_term, flags, old_flags; + char c; + int flushed = 0; + sigset_t newset; + sigset_t oldset; + + in = fileno(stdin); + out = fileno(stdout); + + (void) sigemptyset (&newset); + (void) sigaddset (&newset, SIGINT); + (void) sigaddset (&newset, SIGTSTP); + (void) sigaddset (&newset, SIGQUIT); + + (void) sigprocmask (SIG_BLOCK, &newset, &oldset); + + if ((is_term = isatty(in))) + { + + (void) tcgetattr (in, &term_old); + term_new = term_old; + if (do_echo) + term_new.c_lflag |= ECHO; + else + term_new.c_lflag &= ~ECHO; + + if (tcsetattr (in, TCSAFLUSH, &term_new) == 0) + flushed = 1; + + } + else + { + is_term = 0; + if ((flags = fcntl(in, F_GETFL, 0)) >= 0) { + old_flags = flags; + flags |= O_NONBLOCK; + + fcntl(in, F_SETFL, flags); + + while (read(in, &c, 1) > 0) + /* nothing */; + + fcntl(in, F_SETFL, old_flags); + + flushed = 1; + } + } + + (void)write(out, prompt, strlen(prompt)); + + /* well, this looks ugly, but it handles the following end of line + markers: \r \r\0 \r\n \n \n\r, at least at a second pass */ + + p = rh->buf; + for (;;) + { + if (read(in, &c, 1) <= 0) + return NULL; + + if (!flushed && ((c == '\0') || (c == '\r') || (c == '\n'))) { + flushed = 1; + continue; + } + + if ((c == '\r') || (c == '\n')) + break; + + flushed = 1; + + if (p < rh->buf + GETSTR_LENGTH) + { + if (do_echo && !is_term) + (void)write(out, &c, 1); + *p++ = c; + } + } + + *p = '\0'; + + if (!do_echo || !is_term) (void)write(out, "\r\n", 2); + + if (is_term) + tcsetattr (in, TCSAFLUSH, &term_old); + else { + if ((flags = fcntl(in, F_GETFL, 0)) >= 0) { + old_flags = flags; + flags |= O_NONBLOCK; + + fcntl(in, F_SETFL, flags); + + while (read(in, &c, 1) > 0) + /* nothing */; + + fcntl(in, F_SETFL, old_flags); + } + } + + (void) sigprocmask (SIG_SETMASK, &oldset, NULL); + + return rh->buf; +} +#endif +void rc_mdelay(int msecs) +{ + struct timeval tv; + + tv.tv_sec = (int) msecs / 1000; + tv.tv_usec = (msecs % 1000) * 1000; + + select(0, NULL, NULL, NULL, &tv); +} + +/* + * Function: rc_mksid + * + * Purpose: generate a quite unique string + * + * Remarks: not that unique at all... + * + */ + +char * +rc_mksid (rc_handle *rh) +{ + snprintf (rh->buf1, sizeof(rh->buf1), "%08lX%04X", (unsigned long int) time (NULL), (unsigned int) getpid ()); + return rh->buf1; +} + +/* + * Function: rc_new + * + * Purpose: Initialises new Radius Client handle + * + */ + +rc_handle * +rc_new(void) +{ + rc_handle *rh; + + rh = malloc(sizeof(*rh)); + if (rh == NULL) { + rc_log(LOG_CRIT, "rc_new: out of memory"); + return NULL; + } + memset(rh, 0, sizeof(*rh)); + return rh; +} + +/* + * Function: rc_destroy + * + * Purpose: Destroys Radius Client handle reclaiming all memory + * + */ + +void +rc_destroy(rc_handle *rh) +{ + + rc_map2id_free(rh); + rc_dict_free(rh); + rc_config_free(rh); + if (rh->this_host_bind_ipaddr != NULL) + free(rh->this_host_bind_ipaddr); + free(rh); +} + +/* + * Function: rc_fgetln + * + * Purpose: Get next line from the stream. + * + */ + +char * +rc_fgetln(FILE *fp, size_t *len) +{ + static char *buf = NULL; + static size_t bufsiz = 0; + char *ptr; + + if (buf == NULL) { + bufsiz = RC_BUFSIZ; + if ((buf = malloc(bufsiz)) == NULL) + return NULL; + } + + if (fgets(buf, (int)bufsiz, fp) == NULL) + return NULL; + *len = 0; + + while ((ptr = strchr(&buf[*len], '\n')) == NULL) { + size_t nbufsiz = bufsiz + RC_BUFSIZ; + char *nbuf = realloc(buf, nbufsiz); + + if (nbuf == NULL) { + int oerrno = errno; + free(buf); + errno = oerrno; + buf = NULL; + return NULL; + } else + buf = nbuf; + + *len = bufsiz; + if (fgets(&buf[bufsiz], RC_BUFSIZ, fp) == NULL) + return buf; + + bufsiz = nbufsiz; + } + + *len = (ptr - buf) + 1; + return buf; +} + +/* + * Function: rc_getctime + * + * Purpose: Get current time (seconds since epoch) expressed as + * double-precision floating point number. + * + */ + +double +rc_getctime(void) +{ + struct timeval timev; + + if (gettimeofday(&timev, NULL) == -1) + return -1; + + return timev.tv_sec + ((double)timev.tv_usec) / 1000000.0; +} diff --git a/src/plugins/vbng/vbng.api b/src/plugins/vbng/vbng.api new file mode 100644 index 0000000..eba9a10 --- /dev/null +++ b/src/plugins/vbng/vbng.api @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017 Intel Corp and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** \brief vBNG DHCP config add / del request + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param rx_vrf_id - Rx/interface vrf id + @param server_vrf_id - server vrf id + @param is_add - add the config if non-zero, else delete + @param remote_addr[] - DHCP server address + @param local_addr[] - Local Address which could reach DHCP server +*/ +define vbng_dhcp4_config +{ + u32 client_index; + u32 context; + u32 rx_vrf_id; + u32 server_vrf_id; + u8 is_add; + u8 remote_addr[16]; + u8 local_addr[16]; +}; + +/** \brief vBNG DHCP config response + @param context - sender context, to match reply w/ request + @param retval - return code for the request +*/ +define vbng_dhcp4_config_reply +{ + u32 context; + i32 retval; +}; + +/* + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/plugins/vbng/vbng_aaa.c b/src/plugins/vbng/vbng_aaa.c new file mode 100644 index 0000000..5e8861f --- /dev/null +++ b/src/plugins/vbng/vbng_aaa.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017 Intel and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include +#include + +int +process(void *rh, VALUE_PAIR *send, int nas_port) +{ + VALUE_PAIR *received = NULL; + char msg[PW_MAX_MSG_SIZE]; + int retval; + + retval = rc_auth(rh, nas_port, send, &received, msg); + if (retval == OK_RC && received != NULL) { + rc_avpair_free(received); + } + + return retval; +} + +int +vbng_auth(vbng_dhcp4_main_t *dm, int argc, char **argv) +{ + int i, nas_port = dm->config.nas_port; + char *rc_conf = (char *)dm->config.config_file; + VALUE_PAIR *send, **vp; + void *rh; + + if ((rh = rc_read_config(rc_conf)) == NULL) { + fprintf(stderr, "error opening radius configuration file\n"); + return (1); + } + + if (rc_read_dictionary(rh, rc_conf_str(rh, "dictionary")) != 0) { + fprintf(stderr, "error reading radius dictionary\n"); + return (2); + } + + send = NULL; + vp = &send; + for (i = 0; i < argc; i++) { + if (rc_avpair_parse(rh, argv[i], vp) < 0) { + fprintf(stderr, "%s: can't parse AV pair\n", argv[i]); + return (3); + } + vp = &send->next; + } + + return process(rh, send, nas_port); +} + diff --git a/src/plugins/vbng/vbng_aaa.h b/src/plugins/vbng/vbng_aaa.h new file mode 100644 index 0000000..411a753 --- /dev/null +++ b/src/plugins/vbng/vbng_aaa.h @@ -0,0 +1,34 @@ +/* + * vbng_aaa.h - vBNG FreeRADIUS client commons. + * + * Copyright (c) 2017 Intel and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _VBNG_AAA_H_ +#define _VBNG_AAA_H_ + +#include + +/* Common configuration for RADIUS client */ +#define AAA_DEFAULT_NAS_PORT 5060 +#define AAA_DEFAULT_CONFIG_FILE "/etc/vpp/vbng-aaa.cfg" + +#define BUF_LEN 4096 + +/* String template for the vAAA attributes */ +#define STR_TPL_ATTR_DHCP_AGENT_CIRCUIT_ID "DHCP-Agent-Circuit-Id=%c" +#define STR_TPL_ATTR_DHCP_AGENT_REMOTE_ID "DHCP-Agent-Remote-Id=%c" + +int vbng_auth(vbng_dhcp4_main_t *dm, int argc, char **argv); + +#endif /* _VBNG_AAA_H_ */ diff --git a/src/plugins/vbng/vbng_all_api_h.h b/src/plugins/vbng/vbng_all_api_h.h new file mode 100644 index 0000000..3f74427 --- /dev/null +++ b/src/plugins/vbng/vbng_all_api_h.h @@ -0,0 +1,18 @@ +/* + * vbng_all_api_h.h - skeleton vpp engine plug-in api #include file + * + * Copyright (c) 2017 Intel and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include diff --git a/src/plugins/vbng/vbng_api.c b/src/plugins/vbng/vbng_api.c new file mode 100644 index 0000000..4080f77 --- /dev/null +++ b/src/plugins/vbng/vbng_api.c @@ -0,0 +1,123 @@ +/* + *------------------------------------------------------------------ + * vbng_api.c - vbng api + * + * Copyright (c) 2017 Intel Corp and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------ + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#define vl_typedefs /* define message structures */ +#include +#undef vl_typedefs + +#define vl_endianfun /* define message structures */ +#include +#undef vl_endianfun + +/* instantiate all the print functions we know about */ +#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) +#define vl_printfun +#include +#undef vl_printfun + +#include + +#define foreach_vpe_api_msg \ +_(VBNG_DHCP4_CONFIG,vbng_dhcp4_config) + +static void vl_api_vbng_dhcp4_config_t_handler + (vl_api_vbng_dhcp4_config_t * mp) +{ + vl_api_vbng_dhcp4_config_reply_t *rmp; + ip46_address_t src, server; + int rv = -1; + + ip46_address_reset (&src); + ip46_address_reset (&server); + + clib_memcpy (&src.ip4, mp->local_addr, sizeof (src.ip4)); + clib_memcpy (&server.ip4, mp->remote_addr, sizeof (server.ip4)); + + rv = dhcp4_proxy_set_server (&server, + &src, + (u32) ntohl (mp->rx_vrf_id), + (u32) ntohl (mp->server_vrf_id), + (int) (mp->is_add == 0)); + + + REPLY_MACRO (VL_API_VBNG_DHCP4_CONFIG_REPLY); +} + +/* + * vbng_api_hookup + * Add vpe's API message handlers to the table. + * vlib has alread mapped shared memory and + * added the client registration handlers. + * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process() + */ +#define vl_msg_name_crc_list +#include +#undef vl_msg_name_crc_list + +static void +setup_message_id_table (api_main_t * am) +{ +#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id); + foreach_vl_msg_name_crc_vbng; +#undef _ +} + +static clib_error_t * +vbng_api_hookup (vlib_main_t * vm) +{ + api_main_t *am = &api_main; + +#define _(N,n) \ + vl_msg_api_set_handlers(VL_API_##N, #n, \ + vl_api_##n##_t_handler, \ + vl_noop_handler, \ + vl_api_##n##_t_endian, \ + vl_api_##n##_t_print, \ + sizeof(vl_api_##n##_t), 1); + foreach_vpe_api_msg; +#undef _ + + /* + * Set up the (msg_name, crc, message-id) table + */ + setup_message_id_table (am); + + return 0; +} + +VLIB_API_INIT_FUNCTION (vbng_api_hookup); + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/plugins/vbng/vbng_dhcp4.c b/src/plugins/vbng/vbng_dhcp4.c new file mode 100644 index 0000000..ed79df4 --- /dev/null +++ b/src/plugins/vbng/vbng_dhcp4.c @@ -0,0 +1,160 @@ +/* + * vbng_dhcp4.c: common dhcp v4 processing + * + * Copyright (c) 2017 Intel Corp and/or its affiliates and others. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +/** + * @brief Shard 4/6 instance of DHCP main + */ +vbng_dhcp4_main_t vbng_dhcp4_main; + +void +vbng_dhcp4_walk (vbng_dhcp4_walk_fn_t fn, + void *ctx) +{ + vbng_dhcp4_main_t *vdm = &vbng_dhcp4_main; + dhcp_proxy_t * server; + u32 server_index, i; + + vec_foreach_index (i, vdm->dhcp_server_index_by_rx_fib_index) + { + server_index = vdm->dhcp_server_index_by_rx_fib_index[i]; + if (~0 == server_index) + continue; + + server = pool_elt_at_index (vdm->dhcp4_servers, server_index); + + if (!fn(server, ctx)) + break; + } +} + +static u32 +dhcp_proxy_server_find (dhcp_proxy_t *proxy, + fib_protocol_t proto, + ip46_address_t *addr, + u32 server_table_id) +{ + dhcp_server_t *server; + u32 ii, fib_index; + + vec_foreach_index(ii, proxy->dhcp_servers) + { + server = &proxy->dhcp_servers[ii]; + fib_index = fib_table_find(proto, server_table_id); + + if (ip46_address_is_equal(&server->dhcp_server, + addr) && + (server->server_fib_index == fib_index)) + { + return (ii); + } + } + return (~0); +} + +int +vbng_dhcp4_server_del (fib_protocol_t proto, + u32 rx_fib_index, + ip46_address_t *addr, + u32 server_table_id) +{ + vbng_dhcp4_main_t *vdm = &vbng_dhcp4_main; + dhcp_proxy_t *proxy = 0; + + proxy = vbng_dhcp4_get_server(vdm, rx_fib_index); + + if (NULL != proxy) + { + dhcp_server_t *server; + u32 index; + + index = dhcp_proxy_server_find(proxy, proto, addr, server_table_id); + + if (~0 != index) + { + server = &proxy->dhcp_servers[index]; + fib_table_unlock (server->server_fib_index, proto); + + vec_del1(proxy->dhcp_servers, index); + + if (0 == vec_len(proxy->dhcp_servers)) + { + /* no servers left, delete the proxy config */ + vdm->dhcp_server_index_by_rx_fib_index[rx_fib_index] = ~0; + vec_free(proxy->dhcp_servers); + pool_put (vdm->dhcp4_servers, proxy); + return (1); + } + } + } + + /* the proxy still exists */ + return (0); +} + +int +vbng_dhcp4_server_add (fib_protocol_t proto, + ip46_address_t *addr, + ip46_address_t *src_address, + u32 rx_fib_index, + u32 server_table_id) +{ + vbng_dhcp4_main_t *vdm = &vbng_dhcp4_main; + dhcp_proxy_t * proxy = 0; + int new = 0; + + proxy = vbng_dhcp4_get_server(vdm, rx_fib_index); + + if (NULL == proxy) + { + vec_validate_init_empty(vdm->dhcp_server_index_by_rx_fib_index, + rx_fib_index, + ~0); + + pool_get (vdm->dhcp4_servers, proxy); + memset (proxy, 0, sizeof (*proxy)); + new = 1; + + vdm->dhcp_server_index_by_rx_fib_index[rx_fib_index] = + proxy - vdm->dhcp4_servers; + + proxy->dhcp_src_address = *src_address; + proxy->rx_fib_index = rx_fib_index; + } + else + { + if (~0 != dhcp_proxy_server_find(proxy, proto, addr, server_table_id)) + { + return (new); + } + } + + dhcp_server_t server = { + .dhcp_server = *addr, + .server_fib_index = fib_table_find_or_create_and_lock(proto, + server_table_id), + }; + + vec_add1(proxy->dhcp_servers, server); + + return (new); +} + diff --git a/src/plugins/vbng/vbng_dhcp4.h b/src/plugins/vbng/vbng_dhcp4.h new file mode 100644 index 0000000..2f41575 --- /dev/null +++ b/src/plugins/vbng/vbng_dhcp4.h @@ -0,0 +1,139 @@ +/* + * vbng_dhcp4.h: DHCP v4 common functions/types + * + * Copyright (c) 2017 Intel Corp and/or its affiliates and others. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _VBNG_DHCP4_H_ +#define _VBNG_DHCP4_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef enum { +#define vbng_dhcp4_error(n,s) VBNG_DHCP4_ERROR_##n, +#include +#undef vbng_dhcp4_error + VBNG_DHCP4_N_ERROR, +} vbng_dhcp4_error_t; + +#define VBNG_AAA_DISABLED 0 +#define VBNG_AAA_ENABLED 1 + +typedef struct { + int is_enabled; + u32 nas_port; /* AAA server port */ + u8 *config_file; /* Radius Client config file path */ +} vbng_aaa_config_t; + +/** + * @brief Global configuration for the vBNG plugin. + */ +typedef struct { + /* Pool of DHCP servers */ + dhcp_proxy_t *dhcp4_servers; + + /* Pool of selected DHCP server. Zero is the default server */ + u32 * dhcp_server_index_by_rx_fib_index; + + /* to drop pkts in server-to-client direction */ + u32 error_drop_node_index; + + /* Configuration for the AAA client */ + vbng_aaa_config_t config; + + /* convenience */ + vlib_main_t * vlib_main; + vnet_main_t * vnet_main; +} vbng_dhcp4_main_t; + +extern vbng_dhcp4_main_t vbng_dhcp4_main; + +/** + * @brief Add a new DHCP proxy server configuration. + * @return 1 is the config is new, + * 0 otherwise (implying a modify of an existing) + */ +int vbng_dhcp4_server_add(fib_protocol_t proto, + ip46_address_t *addr, + ip46_address_t *src_address, + u32 rx_fib_iindex, + u32 server_table_id); + +/** + * @brief Delete a DHCP proxy config + * @return 1 if the proxy is deleted, 0 otherwise + */ +int vbng_dhcp4_server_del(fib_protocol_t proto, + u32 rx_fib_index, + ip46_address_t *addr, + u32 server_table_id); + +u32 +dhcp_proxy_rx_table_get_table_id (fib_protocol_t proto, + u32 fib_index); + +/** + * @brief Callback function invoked for each DHCP proxy entry + * return 0 to break the walk, non-zero otherwise. + */ +typedef int (*vbng_dhcp4_walk_fn_t)(dhcp_proxy_t *server, + void *ctx); + +/** + * @brief Walk/Visit each vBNG DHCP server configurations + */ +void vbng_dhcp4_walk(vbng_dhcp4_walk_fn_t fn, + void *ctx); + +/** + * @brief Get the DHCP proxy server data for the FIB index + */ +static inline dhcp_proxy_t * +vbng_dhcp4_get_server(vbng_dhcp4_main_t *vm, + u32 rx_fib_index) +{ + dhcp_proxy_t *s = NULL; + + if (vec_len(vm->dhcp_server_index_by_rx_fib_index) > rx_fib_index && + vm->dhcp_server_index_by_rx_fib_index[rx_fib_index] != ~0) + { + s = pool_elt_at_index ( + vm->dhcp4_servers, + vm->dhcp_server_index_by_rx_fib_index[rx_fib_index]); + } + + return (s); +} + +int vbng_dhcp4_set_server(ip46_address_t *addr, + ip46_address_t *src_addr, + u32 rx_table_id, + u32 server_table_id, + int is_del); + +#define DHCP_PACKET_OPTION_82 82 +#define DHCP_PACKET_OPTION82_SUB1 1 +#define DHCP_PACKET_OPTION82_SUB2 2 +#define DHCP_PACKET_OPTION82_SUB5 5 + +#endif /* _VBNG_DHCP4_H_ */ diff --git a/src/plugins/vbng/vbng_dhcp4_err.def b/src/plugins/vbng/vbng_dhcp4_err.def new file mode 100644 index 0000000..23f2d0d --- /dev/null +++ b/src/plugins/vbng/vbng_dhcp4_err.def @@ -0,0 +1,29 @@ +/* + * vbng_dhcp4_err.def: VBNG DHCP4 Errors + * + * Copyright (c) 2017 Intel Corp and/or its affiliates and others. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +vbng_dhcp4_error (NONE, "no error") +vbng_dhcp4_error (NO_SERVER, "no dhcp server configured") +vbng_dhcp4_error (RELAY_TO_SERVER, "DHCP packets relayed to the server") +vbng_dhcp4_error (RELAY_TO_CLIENT, "DHCP packets relayed to clients") +vbng_dhcp4_error (NO_INTERFACE_ADDRESS, "DHCP no interface address") +vbng_dhcp4_error (BAD_YIADDR, "DHCP packets with bad your_ip_address fields") +vbng_dhcp4_error (BAD_SVR_FIB_OR_ADDRESS, "DHCP packets not from DHCP server or server FIB.") +vbng_dhcp4_error (PKT_TOO_BIG, "DHCP packets which are too big.") +vbng_dhcp4_error (AAA_FAILURE, "DHCP packets failed to pass the AAA check.") +vbng_dhcp4_error (NO_OPTION_82, "DHCP option 82 missing") +vbng_dhcp4_error (BAD_OPTION_82_ITF, "Bad DHCP option 82 interface value") +vbng_dhcp4_error (BAD_OPTION_82_ADDR, "Bad DHCP option 82 address value") diff --git a/src/plugins/vbng/vbng_dhcp4_node.c b/src/plugins/vbng/vbng_dhcp4_node.c new file mode 100644 index 0000000..205959b --- /dev/null +++ b/src/plugins/vbng/vbng_dhcp4_node.c @@ -0,0 +1,1024 @@ +/* + * proxy_node.c: dhcp proxy node processing + * + * Copyright (c) 2013 Cisco and/or its affiliates and others. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +static char * vbng_dhcp4_error_strings[] = { +#define vbng_dhcp4_error(n,s) s, +#include +#undef vbng_dhcp4_error +}; + +#define foreach_vbng_dhcp4_to_server_input_next \ + _ (DROP, "error-drop") \ + _ (LOOKUP, "ip4-lookup") \ + _ (SEND_TO_CLIENT, "vbng-dhcp-to-client") + +typedef enum { +#define _(s,n) VBNG_DHCP4_TO_SERVER_INPUT_NEXT_##s, + foreach_vbng_dhcp4_to_server_input_next +#undef _ + VBNG_DHCP4_TO_SERVER_INPUT_N_NEXT, +} vbng_dhcp4_to_server_input_next_t; + +typedef struct { + /* 0 => to server, 1 => to client */ + int which; + ip4_address_t trace_ip4_address; + u32 error; + u32 sw_if_index; + u32 original_sw_if_index; +} dhcp_proxy_trace_t; + +#define VPP_DHCP_OPTION82_SUB1_SIZE 6 +#define VPP_DHCP_OPTION82_SUB5_SIZE 6 +#define VPP_DHCP_OPTION82_VSS_SIZE 12 +#define VPP_DHCP_OPTION82_SIZE (VPP_DHCP_OPTION82_SUB1_SIZE + \ + VPP_DHCP_OPTION82_SUB5_SIZE + \ + VPP_DHCP_OPTION82_VSS_SIZE +3) + +static vlib_node_registration_t vbng_dhcp4_to_server_node; +static vlib_node_registration_t vbng_dhcp4_to_client_node; + +static u8 * +format_dhcp_proxy_trace (u8 * s, va_list * args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + dhcp_proxy_trace_t * t = va_arg (*args, dhcp_proxy_trace_t *); + + if (t->which == 0) + s = format (s, "DHCP proxy: sent to server %U\n", + format_ip4_address, &t->trace_ip4_address, t->error); + else + s = format (s, "DHCP proxy: broadcast to client from %U\n", + format_ip4_address, &t->trace_ip4_address); + + if (t->error != (u32)~0) + s = format (s, " error: %s\n", vbng_dhcp4_error_strings[t->error]); + + s = format (s, " original_sw_if_index: %d, sw_if_index: %d\n", + t->original_sw_if_index, t->sw_if_index); + + return s; +} + +static u8 * +format_dhcp_proxy_header_with_length (u8 * s, va_list * args) +{ + dhcp_header_t * h = va_arg (*args, dhcp_header_t *); + u32 max_header_bytes = va_arg (*args, u32); + u32 header_bytes; + + header_bytes = sizeof (h[0]); + if (max_header_bytes != 0 && header_bytes > max_header_bytes) + return format (s, "dhcp header truncated"); + + s = format (s, "DHCP Proxy"); + + return s; +} + +static uword +vbng_dhcp_to_server_input (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * from_frame) +{ + u32 n_left_from, next_index, * from, * to_next; + vbng_dhcp4_main_t *dm = &vbng_dhcp4_main; + from = vlib_frame_vector_args (from_frame); + n_left_from = from_frame->n_vectors; + u32 pkts_to_server=0, pkts_to_client=0, pkts_no_server=0; + u32 pkts_no_interface_address=0; + u32 pkts_too_big=0, pkts_aaa_fail = 0; + ip4_main_t * im = &ip4_main; + + next_index = node->cached_next_index; + + while (n_left_from > 0) + { + u32 n_left_to_next; + + vlib_get_next_frame (vm, node, next_index, + to_next, n_left_to_next); + + while (n_left_from > 0 && n_left_to_next > 0) + { + u32 bi0; + vlib_buffer_t * b0; + udp_header_t * u0; + dhcp_header_t * h0; + ip4_header_t * ip0; + u32 next0; + u32 old0, new0; + ip_csum_t sum0; + u32 error0 = (u32) ~0; + u32 sw_if_index = 0; + u32 original_sw_if_index = 0; + u8 *end = NULL; + u32 fib_index; + dhcp_proxy_t *proxy; + dhcp_server_t *server; + u32 rx_sw_if_index; + dhcp_option_t *o; + u32 len = 0; + vlib_buffer_free_list_t *fl; + u8 is_discover = 0; + + bi0 = from[0]; + from += 1; + n_left_from -= 1; + + b0 = vlib_get_buffer (vm, bi0); + + h0 = vlib_buffer_get_current (b0); + + /* + * udp_local hands us the DHCP header, need udp hdr, + * ip hdr to relay to server + */ + vlib_buffer_advance (b0, -(sizeof(*u0))); + u0 = vlib_buffer_get_current (b0); + + /* This blows. Return traffic has src_port = 67, dst_port = 67 */ + if (u0->src_port == clib_net_to_host_u16(UDP_DST_PORT_dhcp_to_server)) + { + vlib_buffer_advance (b0, sizeof(*u0)); + next0 = VBNG_DHCP4_TO_SERVER_INPUT_NEXT_SEND_TO_CLIENT; + error0 = 0; + pkts_to_client++; + goto do_enqueue; + } + + rx_sw_if_index = vnet_buffer(b0)->sw_if_index[VLIB_RX]; + + fib_index = im->fib_index_by_sw_if_index [rx_sw_if_index]; + proxy = vbng_dhcp4_get_server(dm, fib_index); + + if (PREDICT_FALSE (NULL == proxy)) + { + error0 = VBNG_DHCP4_ERROR_NO_SERVER; + next0 = VBNG_DHCP4_TO_SERVER_INPUT_NEXT_DROP; + pkts_no_server++; + goto do_trace; + } + + server = &proxy->dhcp_servers[0]; + vlib_buffer_advance (b0, -(sizeof(*ip0))); + ip0 = vlib_buffer_get_current (b0); + + /* disable UDP checksum */ + u0->checksum = 0; + sum0 = ip0->checksum; + old0 = ip0->dst_address.as_u32; + new0 = server->dhcp_server.ip4.as_u32; + ip0->dst_address.as_u32 = server->dhcp_server.ip4.as_u32; + sum0 = ip_csum_update (sum0, old0, new0, + ip4_header_t /* structure */, + dst_address /* changed member */); + ip0->checksum = ip_csum_fold (sum0); + + sum0 = ip0->checksum; + old0 = ip0->src_address.as_u32; + new0 = proxy->dhcp_src_address.ip4.as_u32; + ip0->src_address.as_u32 = new0; + sum0 = ip_csum_update (sum0, old0, new0, + ip4_header_t /* structure */, + src_address /* changed member */); + ip0->checksum = ip_csum_fold (sum0); + + /* Send to DHCP server via the configured FIB */ + vnet_buffer(b0)->sw_if_index[VLIB_TX] = + server->server_fib_index; + + h0->gateway_ip_address.as_u32 = proxy->dhcp_src_address.ip4.as_u32; + pkts_to_server++; + + o = (dhcp_option_t *) h0->options; + + fib_index = im->fib_index_by_sw_if_index + [vnet_buffer(b0)->sw_if_index[VLIB_RX]]; + + end = b0->data + b0->current_data + b0->current_length; + /* TLVs are not performance-friendly... */ + while (o->option != 0xFF /* end of options */ && (u8 *)o < end) + { + if (DHCP_PACKET_OPTION_MSG_TYPE == o->option) + { + if (DHCP_PACKET_DISCOVER == o->data[0]) + { + is_discover = 1; + } + } + + if (DHCP_PACKET_OPTION_82 == o->option) { + /* For Demo purpose only */ + if (dm->config.is_enabled) { + int i = 0, num_kvs = 0, retval = 0; + char *kv_pairs[1]; + char key_string[32]; + + if (DHCP_PACKET_OPTION82_SUB1 == o->data[0]) { + sprintf(key_string, STR_TPL_ATTR_DHCP_AGENT_CIRCUIT_ID, o->data[2]); + for (i = 1; i < o->data[1]; i++) { + sprintf(key_string, "%s%c", key_string, o->data[2 + i]); + } + } + + if (DHCP_PACKET_OPTION82_SUB2 == o->data[0]) { + sprintf(key_string, STR_TPL_ATTR_DHCP_AGENT_REMOTE_ID, o->data[2]); + for (i = 1; i < o->data[1]; i++) { + sprintf(key_string, "%s%c", key_string, o->data[2 + i]); + } + } + + kv_pairs[num_kvs] = key_string; + num_kvs++; + + retval = vbng_auth(dm, num_kvs, kv_pairs); + if (retval) { + if (retval == 1 /* TIMEOUT_RC */) { + dm->config.is_enabled = VBNG_AAA_DISABLED; + } + error0 = VBNG_DHCP4_ERROR_AAA_FAILURE; + next0 = VBNG_DHCP4_TO_SERVER_INPUT_NEXT_DROP; + pkts_aaa_fail++; + goto do_trace; + } + } + + fl = vlib_buffer_get_free_list (vm, b0->free_list_index); + if (((u8 *)o - (u8 *)b0->data + (VPP_DHCP_OPTION82_SUB1_SIZE + VPP_DHCP_OPTION82_SUB5_SIZE)) + > fl->n_data_bytes) + { + next0 = VBNG_DHCP4_TO_SERVER_INPUT_NEXT_DROP; + pkts_too_big++; + goto do_trace; + } + + /* Begin to appending new sub-options */ + { + vnet_main_t *vnm = vnet_get_main(); + u16 old_l0, new_l0, orig_len = 0; + ip4_address_t _ia0, * ia0 = &_ia0; + vnet_sw_interface_t *swif; + sw_if_index = 0; + original_sw_if_index = 0; + + original_sw_if_index = sw_if_index = + vnet_buffer(b0)->sw_if_index[VLIB_RX]; + swif = vnet_get_sw_interface (vnm, sw_if_index); + if (swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED) + sw_if_index = swif->unnumbered_sw_if_index; + + /* + * Get the first ip4 address on the [client-side] + * RX interface, if not unnumbered. otherwise use + * the loopback interface's ip address. + */ + ia0 = ip4_interface_first_address(&ip4_main, sw_if_index, 0); + + if (ia0 == 0) + { + error0 = VBNG_DHCP4_ERROR_NO_INTERFACE_ADDRESS; + next0 = VBNG_DHCP4_TO_SERVER_INPUT_NEXT_DROP; + pkts_no_interface_address++; + goto do_trace; + } + + orig_len = o->length; + o->data[orig_len + 0] = 1; /* suboption 1, circuit ID (=FIB id) */ + o->data[orig_len + 1] = 4; /* length of suboption */ + o->data[orig_len + 2] = (original_sw_if_index >> 24) & 0xFF; + o->data[orig_len + 3] = (original_sw_if_index >> 16) & 0xFF; + o->data[orig_len + 4] = (original_sw_if_index >> 8) & 0xFF; + o->data[orig_len + 5] = (original_sw_if_index >> 0) & 0xFF; + o->data[orig_len + 6] = 5; /* suboption 5 (client RX intfc address) */ + o->data[orig_len + 7] = 4; /* length 4 */ + o->data[orig_len + 8] = ia0->as_u8[0]; + o->data[orig_len + 9] = ia0->as_u8[1]; + o->data[orig_len + 10] = ia0->as_u8[2]; + o->data[orig_len + 11] = ia0->as_u8[3]; + o->data[orig_len + 12] = 0xFF; + o->length += 12; /* 12 octets appended*/ + + len = o->length + 3; + b0->current_length += len; + /* Fix IP header length and checksum */ + old_l0 = ip0->length; + new_l0 = clib_net_to_host_u16 (old_l0); + new_l0 += len; + new_l0 = clib_host_to_net_u16 (new_l0); + ip0->length = new_l0; + sum0 = ip0->checksum; + sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t, + length /* changed member */); + ip0->checksum = ip_csum_fold (sum0); + + /* Fix UDP length */ + new_l0 = clib_net_to_host_u16 (u0->length); + new_l0 += len; + u0->length = clib_host_to_net_u16 (new_l0); + } + } + + o = (dhcp_option_t *) (((uword) o) + (o->length + 2)); + } + + next0 = VBNG_DHCP4_TO_SERVER_INPUT_NEXT_LOOKUP; + + /* + * If we have multiple servers configured and this is the + * client's discover message, then send copies to each of + * those servers + */ + if (is_discover && vec_len(proxy->dhcp_servers) > 1) + { + u32 ii; + + for (ii = 1; ii < vec_len(proxy->dhcp_servers); ii++) + { + vlib_buffer_t *c0; + u32 ci0; + + c0 = vlib_buffer_copy(vm, b0); + ci0 = vlib_get_buffer_index(vm, c0); + server = &proxy->dhcp_servers[ii]; + + ip0 = vlib_buffer_get_current (c0); + + sum0 = ip0->checksum; + old0 = ip0->dst_address.as_u32; + new0 = server->dhcp_server.ip4.as_u32; + ip0->dst_address.as_u32 = server->dhcp_server.ip4.as_u32; + sum0 = ip_csum_update (sum0, old0, new0, + ip4_header_t /* structure */, + dst_address /* changed member */); + ip0->checksum = ip_csum_fold (sum0); + + to_next[0] = ci0; + to_next += 1; + n_left_to_next -= 1; + + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, + to_next, n_left_to_next, + ci0, next0); + + if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) + { + dhcp_proxy_trace_t *tr; + + tr = vlib_add_trace (vm, node, c0, sizeof (*tr)); + tr->which = 0; /* to server */ + tr->error = error0; + tr->original_sw_if_index = original_sw_if_index; + tr->sw_if_index = sw_if_index; + if (next0 == VBNG_DHCP4_TO_SERVER_INPUT_NEXT_LOOKUP) + tr->trace_ip4_address.as_u32 = server->dhcp_server.ip4.as_u32; + } + + if (PREDICT_FALSE(0 == n_left_to_next)) + { + vlib_put_next_frame (vm, node, next_index, + n_left_to_next); + vlib_get_next_frame (vm, node, next_index, + to_next, n_left_to_next); + } + } + } + do_trace: + if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) + { + dhcp_proxy_trace_t *tr = vlib_add_trace (vm, node, + b0, sizeof (*tr)); + tr->which = 0; /* to server */ + tr->error = error0; + tr->original_sw_if_index = original_sw_if_index; + tr->sw_if_index = sw_if_index; + if (next0 == VBNG_DHCP4_TO_SERVER_INPUT_NEXT_LOOKUP) + tr->trace_ip4_address.as_u32 = + proxy->dhcp_servers[0].dhcp_server.ip4.as_u32; + } + + do_enqueue: + to_next[0] = bi0; + to_next += 1; + n_left_to_next -= 1; + + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, + to_next, n_left_to_next, + bi0, next0); + } + + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + vlib_node_increment_counter (vm, vbng_dhcp4_to_server_node.index, + VBNG_DHCP4_ERROR_RELAY_TO_CLIENT, + pkts_to_client); + vlib_node_increment_counter (vm, vbng_dhcp4_to_server_node.index, + VBNG_DHCP4_ERROR_RELAY_TO_SERVER, + pkts_to_server); + vlib_node_increment_counter (vm, vbng_dhcp4_to_server_node.index, + VBNG_DHCP4_ERROR_NO_SERVER, + pkts_no_server); + vlib_node_increment_counter (vm, vbng_dhcp4_to_server_node.index, + VBNG_DHCP4_ERROR_NO_INTERFACE_ADDRESS, + pkts_no_interface_address); + vlib_node_increment_counter (vm, vbng_dhcp4_to_server_node.index, + VBNG_DHCP4_ERROR_PKT_TOO_BIG, + pkts_too_big); + vlib_node_increment_counter (vm, vbng_dhcp4_to_server_node.index, + VBNG_DHCP4_ERROR_AAA_FAILURE, + pkts_aaa_fail); + return from_frame->n_vectors; +} + +VLIB_REGISTER_NODE (vbng_dhcp4_to_server_node, static) = { + .function = vbng_dhcp_to_server_input, + .name = "vbng-dhcp-to-server", + /* Takes a vector of packets. */ + .vector_size = sizeof (u32), + + .n_errors = VBNG_DHCP4_N_ERROR, + .error_strings = vbng_dhcp4_error_strings, + + .n_next_nodes = VBNG_DHCP4_TO_SERVER_INPUT_N_NEXT, + .next_nodes = { +#define _(s,n) [VBNG_DHCP4_TO_SERVER_INPUT_NEXT_##s] = n, + foreach_vbng_dhcp4_to_server_input_next +#undef _ + }, + + .format_buffer = format_dhcp_proxy_header_with_length, + .format_trace = format_dhcp_proxy_trace, +}; + +static uword +vbng_dhcp_to_client_input (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * from_frame) +{ + u32 n_left_from, * from; + ethernet_main_t *em = ethernet_get_main (vm); + vbng_dhcp4_main_t *dm = &vbng_dhcp4_main; + vnet_main_t * vnm = vnet_get_main(); + ip4_main_t * im = &ip4_main; + + from = vlib_frame_vector_args (from_frame); + n_left_from = from_frame->n_vectors; + + while (n_left_from > 0) + { + u32 bi0; + vlib_buffer_t * b0; + udp_header_t * u0; + dhcp_header_t * h0; + ip4_header_t * ip0 = 0; + ip4_address_t * ia0 = 0; + u32 old0, new0; + ip_csum_t sum0; + ethernet_interface_t *ei0; + ethernet_header_t *mac0; + vnet_hw_interface_t *hi0; + vlib_frame_t *f0; + u32 * to_next0; + u32 sw_if_index = ~0; + vnet_sw_interface_t *si0; + u32 error0 = (u32)~0; + vnet_sw_interface_t *swif; + u32 fib_index; + dhcp_proxy_t *proxy; + dhcp_server_t *server; + u32 original_sw_if_index = (u32) ~0; + ip4_address_t relay_addr = { + .as_u32 = 0, + }; + + bi0 = from[0]; + from += 1; + n_left_from -= 1; + + b0 = vlib_get_buffer (vm, bi0); + h0 = vlib_buffer_get_current (b0); + + /* + * udp_local hands us the DHCP header, need udp hdr, + * ip hdr to relay to client + */ + vlib_buffer_advance (b0, -(sizeof(*u0))); + u0 = vlib_buffer_get_current (b0); + + vlib_buffer_advance (b0, -(sizeof(*ip0))); + ip0 = vlib_buffer_get_current (b0); + + { + dhcp_option_t *o = (dhcp_option_t *) h0->options; + dhcp_option_t *sub; + + /* Parse through TLVs looking for option 82. + The circuit-ID is the FIB number we need + to track down the client-facing interface */ + + while (o->option != 0xFF /* end of options */ && + (u8 *) o < (b0->data + b0->current_data + b0->current_length)) + { + if (o->option == 82) + { + sub = (dhcp_option_t *) &o->data[0]; + while (sub->option != 0xFF /* end of options */ && + (u8 *) sub < (u8 *)(o + o->length)) { + /* If this is one of ours, it will have + total length 12, circuit-id suboption type, + and the sw_if_index */ + if (sub->option == 1 && sub->length == 4) + { + sw_if_index = ((sub->data[0] << 24) | + (sub->data[1] << 16) | + (sub->data[2] << 8) | + (sub->data[3])); + } + else if (sub->option == 5 && sub->length == 4) + { + relay_addr.as_u8[0] = sub->data[0]; + relay_addr.as_u8[1] = sub->data[1]; + relay_addr.as_u8[2] = sub->data[2]; + relay_addr.as_u8[3] = sub->data[3]; + } + sub = (dhcp_option_t *) + (((uword) sub) + (sub->length + 2)); + } + + } + o = (dhcp_option_t *) (((uword) o) + (o->length + 2)); + } + } + + if (sw_if_index == (u32)~0) + { + error0 = VBNG_DHCP4_ERROR_NO_OPTION_82; + + drop_packet: + vlib_node_increment_counter (vm, vbng_dhcp4_to_client_node.index, + error0, 1); + f0 = vlib_get_frame_to_node (vm, dm->error_drop_node_index); + to_next0 = vlib_frame_vector_args (f0); + to_next0[0] = bi0; + f0->n_vectors = 1; + vlib_put_frame_to_node (vm, dm->error_drop_node_index, f0); + goto do_trace; + } + + if (relay_addr.as_u32 == 0) + { + error0 = VBNG_DHCP4_ERROR_BAD_OPTION_82_ADDR; + goto drop_packet; + } + + if (sw_if_index >= vec_len (im->fib_index_by_sw_if_index)) + { + error0 = VBNG_DHCP4_ERROR_BAD_OPTION_82_ITF; + goto drop_packet; + } + + fib_index = im->fib_index_by_sw_if_index [sw_if_index]; + proxy = vbng_dhcp4_get_server(dm, fib_index); + + if (PREDICT_FALSE (NULL == proxy)) + { + error0 = VBNG_DHCP4_ERROR_NO_SERVER; + goto drop_packet; + } + + vec_foreach(server, proxy->dhcp_servers) + { + if (ip0->src_address.as_u32 == server->dhcp_server.ip4.as_u32) + { + goto server_found; + } + } + + error0 = VBNG_DHCP4_ERROR_BAD_SVR_FIB_OR_ADDRESS; + goto drop_packet; + + server_found: + vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index; + + swif = vnet_get_sw_interface (vnm, sw_if_index); + original_sw_if_index = sw_if_index; + if (swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED) + sw_if_index = swif->unnumbered_sw_if_index; + + ia0 = ip4_interface_first_address (&ip4_main, sw_if_index, 0); + if (ia0 == 0) + { + error0 = VBNG_DHCP4_ERROR_NO_INTERFACE_ADDRESS; + goto drop_packet; + } + + if (relay_addr.as_u32 != ia0->as_u32) + { + error0 = VBNG_DHCP4_ERROR_BAD_YIADDR; + goto drop_packet; + } + + u0->checksum = 0; + u0->dst_port = clib_net_to_host_u16 (UDP_DST_PORT_dhcp_to_client); + sum0 = ip0->checksum; + old0 = ip0->dst_address.as_u32; + new0 = 0xFFFFFFFF; + ip0->dst_address.as_u32 = new0; + sum0 = ip_csum_update (sum0, old0, new0, + ip4_header_t /* structure */, + dst_address /* offset of changed member */); + ip0->checksum = ip_csum_fold (sum0); + + sum0 = ip0->checksum; + old0 = ip0->src_address.as_u32; + new0 = ia0->as_u32; + ip0->src_address.as_u32 = new0; + sum0 = ip_csum_update (sum0, old0, new0, + ip4_header_t /* structure */, + src_address /* offset of changed member */); + ip0->checksum = ip_csum_fold (sum0); + + vlib_buffer_advance (b0, -(sizeof(ethernet_header_t))); + si0 = vnet_get_sw_interface (vnm, original_sw_if_index); + if (si0->type == VNET_SW_INTERFACE_TYPE_SUB) + vlib_buffer_advance (b0, -4 /* space for VLAN tag */); + + mac0 = vlib_buffer_get_current (b0); + + hi0 = vnet_get_sup_hw_interface (vnm, original_sw_if_index); + ei0 = pool_elt_at_index (em->interfaces, hi0->hw_instance); + clib_memcpy (mac0->src_address, ei0->address, sizeof (ei0->address)); + memset (mac0->dst_address, 0xff, sizeof (mac0->dst_address)); + mac0->type = (si0->type == VNET_SW_INTERFACE_TYPE_SUB) ? + clib_net_to_host_u16(0x8100) : clib_net_to_host_u16 (0x0800); + + if (si0->type == VNET_SW_INTERFACE_TYPE_SUB) + { + u32 * vlan_tag = (u32 *)(mac0+1); + u32 tmp; + tmp = (si0->sub.id << 16) | 0x0800; + *vlan_tag = clib_host_to_net_u32 (tmp); + } + + /* $$$ This needs to be rewritten, for sure */ + f0 = vlib_get_frame_to_node (vm, hi0->output_node_index); + to_next0 = vlib_frame_vector_args (f0); + to_next0[0] = bi0; + f0->n_vectors = 1; + vlib_put_frame_to_node (vm, hi0->output_node_index, f0); + + do_trace: + if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) + { + dhcp_proxy_trace_t *tr = vlib_add_trace (vm, node, + b0, sizeof (*tr)); + tr->which = 1; /* to client */ + tr->trace_ip4_address.as_u32 = ia0 ? ia0->as_u32 : 0; + tr->error = error0; + tr->original_sw_if_index = original_sw_if_index; + tr->sw_if_index = sw_if_index; + } + } + return from_frame->n_vectors; +} + +VLIB_REGISTER_NODE (vbng_dhcp4_to_client_node, static) = { + .function = vbng_dhcp_to_client_input, + .name = "vbng-dhcp-to-client", + /* Takes a vector of packets. */ + .vector_size = sizeof (u32), + + .n_errors = VBNG_DHCP4_N_ERROR, + .error_strings = vbng_dhcp4_error_strings, + .format_buffer = format_dhcp_proxy_header_with_length, + .format_trace = format_dhcp_proxy_trace, +}; + +static clib_error_t * +vbng_dhcp4_proxy_init (vlib_main_t * vm) +{ + vbng_dhcp4_main_t *dm = &vbng_dhcp4_main; + vlib_node_t * error_drop_node; + + error_drop_node = vlib_get_node_by_name (vm, (u8 *) "error-drop"); + dm->error_drop_node_index = error_drop_node->index; + + udp_register_dst_port (vm, UDP_DST_PORT_dhcp_to_client, + vbng_dhcp4_to_client_node.index, 1 /* is_ip4 */); + + udp_register_dst_port (vm, UDP_DST_PORT_dhcp_to_server, + vbng_dhcp4_to_server_node.index, 1 /* is_ip4 */); + + dm->vlib_main = vm; + dm->vnet_main = vnet_get_main(); + + return 0; +} + +/* *INDENT-OFF* */ +VLIB_INIT_FUNCTION (vbng_dhcp4_proxy_init); +/* *INDENT-ON* */ + +int +vbng_dhcp4_set_server (ip46_address_t *addr, + ip46_address_t *src_addr, + u32 rx_table_id, + u32 server_table_id, + int is_del) +{ + u32 rx_fib_index = 0; + int rc = 0; + + const fib_prefix_t all_1s = + { + .fp_len = 32, + .fp_addr.ip4.as_u32 = 0xffffffff, + .fp_proto = FIB_PROTOCOL_IP4, + }; + + if (ip46_address_is_zero(addr)) + return VNET_API_ERROR_INVALID_DST_ADDRESS; + + if (ip46_address_is_zero(src_addr)) + return VNET_API_ERROR_INVALID_SRC_ADDRESS; + + rx_fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, + rx_table_id); + + if (is_del) + { + if (vbng_dhcp4_server_del (FIB_PROTOCOL_IP4, rx_fib_index, + addr, server_table_id)) + { + fib_table_entry_special_remove(rx_fib_index, + &all_1s, + FIB_SOURCE_DHCP); + fib_table_unlock (rx_fib_index, FIB_PROTOCOL_IP4); + } + } + else + { + if (vbng_dhcp4_server_add (FIB_PROTOCOL_IP4, + addr, src_addr, + rx_fib_index, server_table_id)) + { + fib_table_entry_special_add(rx_fib_index, + &all_1s, + FIB_SOURCE_DHCP, + FIB_ENTRY_FLAG_LOCAL); + fib_table_lock (rx_fib_index, FIB_PROTOCOL_IP4); + } + } + fib_table_unlock (rx_fib_index, FIB_PROTOCOL_IP4); + + return (rc); +} + +static clib_error_t * +dhcp4_proxy_set_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + ip46_address_t server_addr, src_addr; + u32 server_table_id = 0, rx_table_id = 0; + int is_del = 0; + int set_src = 0, set_server = 0; + + memset(&server_addr, 0, sizeof(server_addr)); + memset(&src_addr, 0, sizeof(src_addr)); + + while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "remote %U", + unformat_ip4_address, &server_addr.ip4)) + set_server = 1; + else if (unformat (input, "server-fib-id %d", &server_table_id)) + ; + else if (unformat (input, "rx-fib-id %d", &rx_table_id)) + ; + else if (unformat(input, "local %U", + unformat_ip4_address, &src_addr.ip4)) + set_src = 1; + else if (unformat (input, "delete") || + unformat (input, "del")) + is_del = 1; + else + break; + } + + if (is_del || (set_server && set_src)) + { + int rv; + + rv = vbng_dhcp4_set_server (&server_addr, &src_addr, rx_table_id, + server_table_id, is_del); + switch (rv) + { + case 0: + return 0; + + case VNET_API_ERROR_INVALID_DST_ADDRESS: + return clib_error_return (0, "Invalid remote address"); + + case VNET_API_ERROR_INVALID_SRC_ADDRESS: + return clib_error_return (0, "Invalid local address"); + + case VNET_API_ERROR_NO_SUCH_ENTRY: + return clib_error_return + (0, "Fib id %d: no per-fib DHCP server configured", rx_table_id); + + default: + return clib_error_return (0, "BUG: rv %d", rv); + } + } + else + return clib_error_return (0, "parse error`%U'", + format_unformat_error, input); +} + +VLIB_CLI_COMMAND (vbng_dhcp4_set_command, static) = { + .path = "set vbng dhcp4", + .short_help = "set vbng dhcp4 [del] remote local [server-fib-id ] [rx-fib-id ]", + .function = dhcp4_proxy_set_command_fn, +}; + +static u8 * +format_dhcp4_proxy_server (u8 * s, va_list * args) +{ + dhcp_proxy_t *proxy = va_arg (*args, dhcp_proxy_t *); + ip4_fib_t * rx_fib, * server_fib; + dhcp_server_t *server; + + if (proxy == 0) + { + s = format (s, "%=14s%=16s%s", "RX FIB", "Src Address", + "Servers FIB,Address"); + return s; + } + + rx_fib = ip4_fib_get(proxy->rx_fib_index); + + s = format (s, "%=14u%=16U", + rx_fib->table_id, + format_ip46_address, &proxy->dhcp_src_address, IP46_TYPE_ANY); + + vec_foreach(server, proxy->dhcp_servers) + { + server_fib = ip4_fib_get(server->server_fib_index); + s = format (s, "%u,%U ", + server_fib->table_id, + format_ip46_address, &server->dhcp_server, IP46_TYPE_ANY); + } + return s; +} + +static int +dhcp4_proxy_show_walk (dhcp_proxy_t *server, + void *ctx) +{ + vlib_main_t * vm = ctx; + + vlib_cli_output (vm, "%U", format_dhcp4_proxy_server, server); + + return (1); +} + +static clib_error_t * +vbng_dhcp4_show_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + vlib_cli_output (vm, "%U", format_dhcp4_proxy_server, NULL /* header line */); + + vbng_dhcp4_walk(dhcp4_proxy_show_walk, vm); + + return (NULL); +} + +VLIB_CLI_COMMAND (vbng_dhcp4_show_command, static) = { + .path = "show vbng dhcp4", + .short_help = "Display vbng DHCP4 configuration info", + .function = vbng_dhcp4_show_command_fn, +}; + +static clib_error_t * +vbng_aaa_set_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + vbng_dhcp4_main_t *dm = &vbng_dhcp4_main; + u8 *config_file = NULL; + u32 nas_port = 0; + int set_config = 0, is_del = 0; + + while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT) { + if (unformat (input, "nas-port %d", &nas_port)) + ; + else if (unformat (input, "config %v", &config_file)) + set_config = 1; + else if (unformat (input, "delete") || + unformat (input, "del")) + is_del = 1; + else + break; + } + + if (!is_del && set_config) { + if (dm->config.is_enabled == VBNG_AAA_ENABLED) { + return 0; + } + + if (nas_port) { + dm->config.nas_port = nas_port; + } else { + dm->config.nas_port = AAA_DEFAULT_NAS_PORT; + } + dm->config.config_file = config_file; + dm->config.is_enabled = VBNG_AAA_ENABLED; + } else if (is_del) { + if (dm->config.is_enabled == VBNG_AAA_DISABLED) { + return 0; + } + + vec_free (dm->config.config_file); + dm->config.config_file = format(0, "%s", AAA_DEFAULT_CONFIG_FILE); + dm->config.nas_port = AAA_DEFAULT_NAS_PORT; + dm->config.is_enabled = VBNG_AAA_DISABLED; + } else { + return clib_error_return (0, "parse error`%U'", + format_unformat_error, input); + } + + return 0; +} + +VLIB_CLI_COMMAND (vbng_aaa_set_command, static) = { + .path = "set vbng aaa", + .short_help = "set vbng aaa [del] config [nas-port ]", + .function = vbng_aaa_set_command_fn, +}; + +static u8 * +format_vbng_aaa_config(u8 *s, va_list *args) +{ + vbng_dhcp4_main_t *dm = &vbng_dhcp4_main; + + s = format(s, "%=8s %=8s %s\n", "Enabled", + "NAS Port", "Config File"); + + s = format(s, "%=8s %=8d %v\n", + dm->config.is_enabled ? "True" : "False", + dm->config.nas_port, + dm->config.config_file); + + return s; +} + +static clib_error_t * +vbng_aaa_show_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + vlib_cli_output (vm, "%U", format_vbng_aaa_config, NULL); + + return (NULL); +} + +VLIB_CLI_COMMAND (vbng_aaa_show_command, static) = { + .path = "show vbng aaa", + .short_help = "Display vbng AAA configuration info", + .function = vbng_aaa_show_command_fn, +}; + +/* *INDENT-OFF* */ +VLIB_PLUGIN_REGISTER () = { + .version = VPP_BUILD_VER, + .description = "DHCP V4 Proxy With Radius Client", +}; +/* *INDENT-ON* */ diff --git a/src/plugins/vbng/vbng_msg_enum.h b/src/plugins/vbng/vbng_msg_enum.h new file mode 100644 index 0000000..1dc1357 --- /dev/null +++ b/src/plugins/vbng/vbng_msg_enum.h @@ -0,0 +1,31 @@ +/* + * vbng_msg_enum.h - vpp engine plug-in message enumeration + * + * Copyright (c) 2017 Intel and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _VBNG_MSG_ENUM_H_ +#define _VBNG_MSG_ENUM_H_ + +#include + +#define vl_msg_id(n,h) n, +typedef enum +{ +#include + /* We'll want to know how many messages IDs we need... */ + VL_MSG_FIRST_AVAILABLE, +} vl_msg_id_t; +#undef vl_msg_id + +#endif /* _VBNG_MSG_ENUM_H_ */ diff --git a/src/vnet.am b/src/vnet.am index 9e099f3..7c107f0 100644 --- a/src/vnet.am +++ b/src/vnet.am @@ -682,31 +682,31 @@ endif ######################################## # DHCP client ######################################## -libvnet_la_SOURCES += \ - vnet/dhcp/client.c \ - vnet/dhcp/client.h \ - vnet/dhcp/dhcp_api.c - -nobase_include_HEADERS += \ - vnet/dhcp/client.h \ - vnet/dhcp/dhcp.api.h - -API_FILES += vnet/dhcp/dhcp.api +#libvnet_la_SOURCES += \ +# vnet/dhcp/client.c \ +# vnet/dhcp/client.h \ +# vnet/dhcp/dhcp_api.c +# +#nobase_include_HEADERS += \ +# vnet/dhcp/client.h \ +# vnet/dhcp/dhcp.api.h +# +#API_FILES += vnet/dhcp/dhcp.api ######################################## # DHCP proxy ######################################## -libvnet_la_SOURCES += \ - vnet/dhcp/dhcp6_proxy_node.c \ - vnet/dhcp/dhcp4_proxy_node.c \ - vnet/dhcp/dhcp_proxy.c - -nobase_include_HEADERS += \ - vnet/dhcp/dhcp4_packet.h \ - vnet/dhcp/dhcp6_packet.h \ - vnet/dhcp/dhcp_proxy.h \ - vnet/dhcp/dhcp6_proxy_error.def \ - vnet/dhcp/dhcp4_proxy_error.def +#libvnet_la_SOURCES += \ +# vnet/dhcp/dhcp6_proxy_node.c \ +# vnet/dhcp/dhcp4_proxy_node.c \ +# vnet/dhcp/dhcp_proxy.c +# +#nobase_include_HEADERS += \ +# vnet/dhcp/dhcp4_packet.h \ +# vnet/dhcp/dhcp6_packet.h \ +# vnet/dhcp/dhcp_proxy.h \ +# vnet/dhcp/dhcp6_proxy_error.def \ +# vnet/dhcp/dhcp4_proxy_error.def ######################################## # ipv6 segment routing diff --git a/src/vpp-api/java/Makefile.am b/src/vpp-api/java/Makefile.am index f18e0c2..cadaa8d 100644 --- a/src/vpp-api/java/Makefile.am +++ b/src/vpp-api/java/Makefile.am @@ -149,6 +149,26 @@ jvpp-snat/io_fd_vpp_jvpp_snat_JVppSnatImpl.h: $(jvpp_registry_ok) $(jvpp_snat_js endif # +# VBNG Plugin +# +if ENABLE_VBNG_PLUGIN +noinst_LTLIBRARIES += libjvpp_vbng.la +libjvpp_vbng_la_SOURCES = jvpp-vbng/jvpp_vbng.c +libjvpp_vbng_la_CPPFLAGS = -Ijvpp-vbng +libjvpp_vbng_la_LIBADD = $(JVPP_LIBS) +libjvpp_vbng_la_DEPENDENCIES = libjvpp_common.la + +BUILT_SOURCES += jvpp-vbng/io_fd_vpp_jvpp_vbng_JVppVbngImpl.h +JAR_FILES += jvpp-vbng-$(PACKAGE_VERSION).jar +CLEANDIRS += jvpp-vbng/target + +jvpp_vbng_json_files = @top_builddir@/plugins/vbng/vbng.api.json + +jvpp-vbng/io_fd_vpp_jvpp_vbng_JVppVbngImpl.h: $(jvpp_registry_ok) $(jvpp_vbng_json_files) + $(call japigen,vbng,JVppVbngImpl) +endif + +# # iOAM Trace Plugin # if ENABLE_IOAM_PLUGIN diff --git a/src/vpp-api/java/jvpp-vbng/jvpp_vbng.c b/src/vpp-api/java/jvpp-vbng/jvpp_vbng.c new file mode 100644 index 0000000..b722a50 --- /dev/null +++ b/src/vpp-api/java/jvpp-vbng/jvpp_vbng.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2017 Intel Corp and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#define vl_typedefs /* define message structures */ +#include +#undef vl_typedefs + +#include +#include +#include + +#if VPPJNI_DEBUG == 1 + #define DEBUG_LOG(...) clib_warning(__VA_ARGS__) +#else + #define DEBUG_LOG(...) +#endif + +#include + +#include "jvpp-vbng/io_fd_vpp_jvpp_vbng_JVppVbngImpl.h" +#include "jvpp_vbng.h" +#include "jvpp-vbng/jvpp_vbng_gen.h" + +/* + * Class: io_fd_vpp_jvpp_vbng_JVppVbngImpl + * Method: init0 + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_io_fd_vpp_jvpp_vbng_JVppVbngImpl_init0 + (JNIEnv *env, jclass clazz, jobject callback, jlong queue_address, jint my_client_index) { + vbng_main_t * plugin_main = &vbng_main; + clib_warning ("Java_io_fd_vpp_jvpp_vbng_JVppVbngImpl_init0"); + + plugin_main->my_client_index = my_client_index; + plugin_main->vl_input_queue = (unix_shared_memory_queue_t *)queue_address; + + plugin_main->callbackObject = (*env)->NewGlobalRef(env, callback); + plugin_main->callbackClass = (jclass)(*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, callback)); + + // verify API has not changed since jar generation + #define _(N) \ + get_message_id(env, #N); + foreach_supported_api_message; + #undef _ + + #define _(N,n) \ + vl_msg_api_set_handlers(get_message_id(env, #N), #n, \ + vl_api_##n##_t_handler, \ + vl_noop_handler, \ + vl_noop_handler, \ + vl_noop_handler, \ + sizeof(vl_api_##n##_t), 1); + foreach_api_reply_handler; + #undef _ +} + +JNIEXPORT void JNICALL Java_io_fd_vpp_jvpp_vbng_JVppVbngImpl_close0 +(JNIEnv *env, jclass clazz) { + vbng_main_t * plugin_main = &vbng_main; + + // cleanup: + (*env)->DeleteGlobalRef(env, plugin_main->callbackClass); + (*env)->DeleteGlobalRef(env, plugin_main->callbackObject); + + plugin_main->callbackClass = NULL; + plugin_main->callbackObject = NULL; +} + +/* Attach thread to JVM and cache class references when initiating JVPP VES */ +jint JNI_OnLoad(JavaVM *vm, void *reserved) { + JNIEnv* env; + + if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_8) != JNI_OK) { + return JNI_EVERSION; + } + + if (cache_class_references(env) != 0) { + clib_warning ("Failed to cache class references\n"); + return JNI_ERR; + } + + return JNI_VERSION_1_8; +} + +/* Clean up cached references when disposing JVPP VES */ +void JNI_OnUnload(JavaVM *vm, void *reserved) { + JNIEnv* env; + if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_8) != JNI_OK) { + return; + } + delete_class_references(env); +} diff --git a/src/vpp-api/java/jvpp-vbng/jvpp_vbng.h b/src/vpp-api/java/jvpp-vbng/jvpp_vbng.h new file mode 100644 index 0000000..62b4cda --- /dev/null +++ b/src/vpp-api/java/jvpp-vbng/jvpp_vbng.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017 Intel Corp and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __included_jvpp_vbng_h__ +#define __included_jvpp_vbng_h__ + +#include +#include +#include +#include +#include +#include + +/* Global state for JVPP-VES */ +typedef struct { + /* Pointer to shared memory queue */ + unix_shared_memory_queue_t * vl_input_queue; + + /* VPP api client index */ + u32 my_client_index; + + /* Callback object and class references enabling asynchronous Java calls */ + jobject callbackObject; + jclass callbackClass; + +} vbng_main_t; + +vbng_main_t vbng_main __attribute__((aligned (64))); + +#endif /* __included_jvpp_vbng_h__ */