diff options
author | Dmitry Kozlov <xeb@mail.ru> | 2017-10-17 23:23:54 +0300 |
---|---|---|
committer | Dmitry Kozlov <xeb@mail.ru> | 2017-10-17 23:33:44 +0300 |
commit | 405a4d8de0048aa77d09380b33a3f06149d16765 (patch) | |
tree | d3de19458bb0d17529e6d029f11b4ecefef56fed /accel-pppd/radius | |
parent | 0a71249f32169ad04fd6a907989578dced3ba9ec (diff) | |
download | accel-ppp-405a4d8de0048aa77d09380b33a3f06149d16765.tar.gz accel-ppp-405a4d8de0048aa77d09380b33a3f06149d16765.zip |
radius: implemented lua support
to get radius object use session:module("radius") function
radius object provides flollowing functions:
radius:attrs() - returns array of attributes {"name" = NAME, "vendor" = VENDOR|nil}
radius:attr(name[,vendor]) - returns value of attribute (may return multiple results)
Example:
function ip_up(ses)
rad = ses:module("radius")
attrs = rad:attrs()
if attrs then
print("attrs:")
for _,a in pairs(attrs) do
io.write("\t")
if a.vendor then io.write(a.vendor..":") end
io.write(a.name.."=")
print(rad:attr(a.name, a.vendor))
end
end
end
Diffstat (limited to 'accel-pppd/radius')
-rw-r--r-- | accel-pppd/radius/CMakeLists.txt | 9 | ||||
-rw-r--r-- | accel-pppd/radius/auth.c | 4 | ||||
-rw-r--r-- | accel-pppd/radius/lua.c | 183 | ||||
-rw-r--r-- | accel-pppd/radius/radius.c | 10 | ||||
-rw-r--r-- | accel-pppd/radius/radius_p.h | 2 |
5 files changed, 207 insertions, 1 deletions
diff --git a/accel-pppd/radius/CMakeLists.txt b/accel-pppd/radius/CMakeLists.txt index db56b5d4..8cb66ce6 100644 --- a/accel-pppd/radius/CMakeLists.txt +++ b/accel-pppd/radius/CMakeLists.txt @@ -14,10 +14,19 @@ IF (BACKUP) SET(sources ${sources} backup.c) ENDIF (BACKUP) +IF (LUA) + INCLUDE_DIRECTORIES(${LUA_INCLUDE_DIR}) + SET(sources ${sources} lua.c) +ENDIF () + ADD_DEFINITIONS(-DDICTIONARY="${CMAKE_INSTALL_PREFIX}/share/accel-ppp/radius/dictionary") ADD_LIBRARY(radius SHARED ${sources}) +IF (LUA) + TARGET_LINK_LIBRARIES(radius luasupp) +ENDIF () + INSTALL(TARGETS radius LIBRARY DESTINATION lib${LIB_SUFFIX}/accel-ppp ) diff --git a/accel-pppd/radius/auth.c b/accel-pppd/radius/auth.c index b5900023..4cc5ff74 100644 --- a/accel-pppd/radius/auth.c +++ b/accel-pppd/radius/auth.c @@ -150,6 +150,10 @@ static void rad_auth_finalize(struct radius_pd_t *rpd, int r) rpd->auth_ctx->cb(rpd->auth_ctx->cb_arg, r); if (rpd->auth_ctx) { + if (r == PWDB_SUCCESS) { + rpd->auth_reply = rpd->auth_ctx->req->reply; + rpd->auth_ctx->req->reply = NULL; + } rad_req_free(rpd->auth_ctx->req); mempool_free(rpd->auth_ctx); rpd->auth_ctx = NULL; diff --git a/accel-pppd/radius/lua.c b/accel-pppd/radius/lua.c new file mode 100644 index 00000000..45f78757 --- /dev/null +++ b/accel-pppd/radius/lua.c @@ -0,0 +1,183 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <arpa/inet.h> + +#include <lua.h> +#include <lauxlib.h> +#include <lualib.h> + +#include "ap_session.h" +#include "radius_p.h" +#include "luasupp.h" +#include "utils.h" + +#define LUA_RADIUS "accel-ppp.radius" + +static int radius_attrs(lua_State *L) +{ + struct radius_pd_t *rpd = luaL_checkudata(L, 1, LUA_RADIUS); + struct rad_attr_t *attr; + int i = 1; + + if (!rpd) + return 0; + + if (!rpd->auth_reply) { + lua_pushnil(L); + return 1; + } + + lua_newtable(L); + + list_for_each_entry(attr, &rpd->auth_reply->attrs, entry) { + lua_createtable(L, 0, 3); + + lua_pushstring(L, attr->attr->name); + lua_setfield(L, -2, "name"); + + if (attr->vendor) + lua_pushstring(L, attr->vendor->name); + else + lua_pushnil(L); + lua_setfield(L, -2, "vendor"); + + lua_rawseti(L, -2, i++); + } + + return 1; +} + +static int radius_attr(lua_State *L) +{ + struct radius_pd_t *rpd = luaL_checkudata(L, 1, LUA_RADIUS); + const char *name; + const char *vendor; + struct rad_attr_t *attr; + struct rad_dict_value_t *val; + char str[256]; + union { + uint64_t ifid; + uint16_t u16[4]; + } ifid_u; + int r = 0; + + if (!rpd) + return 0; + + if (!rpd->auth_reply) { + lua_pushnil(L); + return 1; + } + + name = luaL_checkstring(L, 2); + if (!name) + return 0; + + vendor = luaL_optstring(L, 3, NULL); + + list_for_each_entry(attr, &rpd->auth_reply->attrs, entry) { + if ((attr->vendor && !vendor) || (!attr->vendor && vendor)) + continue; + + if (vendor && strcmp(vendor, attr->vendor->name)) + continue; + + if (strcmp(name, attr->attr->name)) + continue; + + switch (attr->attr->type) { + case ATTR_TYPE_STRING: + lua_pushstring(L, attr->val.string); + break; + case ATTR_TYPE_INTEGER: + val = rad_dict_find_val(attr->attr, attr->val); + if (val) { + lua_pushstring(L, val->name); + break; + } + case ATTR_TYPE_DATE: + lua_pushinteger(L, attr->val.integer); + break; + case ATTR_TYPE_IPADDR: + u_inet_ntoa(attr->val.ipaddr, str); + lua_pushstring(L, str); + break; + case ATTR_TYPE_IFID: + ifid_u.ifid = attr->val.ifid; + sprintf(str, "%x:%x:%x:%x", ntohs(ifid_u.u16[0]), ntohs(ifid_u.u16[1]), ntohs(ifid_u.u16[2]), ntohs(ifid_u.u16[3])); + lua_pushstring(L, str); + break; + case ATTR_TYPE_IPV6ADDR: + inet_ntop(AF_INET6, &attr->val.ipv6addr, str, sizeof(str)); + lua_pushstring(L, str); + break; + case ATTR_TYPE_IPV6PREFIX: + inet_ntop(AF_INET6, &attr->val.ipv6prefix.prefix, str, sizeof(str)); + sprintf(strchr(str, 0), "/%i", attr->val.ipv6prefix.len); + lua_pushstring(L, str); + break; + default: + lua_pushlstring(L, (char *)attr->val.octets, attr->len); + break; + } + + r++; + } + + if (!r) { + lua_pushnil(L); + r = 1; + } + + return r; +} + +static const struct luaL_Reg radius_lib [] = { + {"attrs", radius_attrs}, + {"attr", radius_attr}, + {NULL, NULL} +}; + +static void radius_mod_init(lua_State *L) +{ + luaL_newmetatable(L, LUA_RADIUS); + + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + +#if LUA_VERSION_NUM < 502 + luaL_register(L, NULL, radius_lib); +#else + luaL_setfuncs(L, radius_lib, 0); +#endif +} + +static int radius_mod_get_instance(lua_State *L, struct ap_session *ses) +{ + struct radius_pd_t *rpd = find_pd(ses); + + if (!rpd) { + lua_pushnil(L); + return 1; + } + + lua_pushlightuserdata(L, rpd); + luaL_getmetatable(L, LUA_RADIUS); + lua_setmetatable(L, -2); + + return 1; +} + +static const struct lua_session_module radius_mod = { + .name = "radius", + .init = radius_mod_init, + .get_instance = radius_mod_get_instance, +}; + +static void init() +{ + lua_session_module_register(&radius_mod); +} + +DEFINE_INIT(1, init); diff --git a/accel-pppd/radius/radius.c b/accel-pppd/radius/radius.c index eede9067..b8706015 100644 --- a/accel-pppd/radius/radius.c +++ b/accel-pppd/radius/radius.c @@ -451,6 +451,11 @@ static void ses_started(struct ap_session *ses) log_ppp_warn("radius: failed to add route %s/%i%s\n", dst, fr->mask, gw); } } + + if (rpd->auth_reply) { + rad_packet_free(rpd->auth_reply); + rpd->auth_reply = NULL; + } } static void ses_finishing(struct ap_session *ses) @@ -502,6 +507,9 @@ static void ses_finished(struct ap_session *ses) } } + if (rpd->auth_reply) + rad_packet_free(rpd->auth_reply); + if (rpd->dm_coa_req) dm_coa_cancel(rpd); @@ -832,7 +840,7 @@ static void radius_init(void) ipdb_register(&ipdb); triton_event_register_handler(EV_SES_STARTING, (triton_event_func)ses_starting); - triton_event_register_handler(EV_SES_STARTED, (triton_event_func)ses_started); + triton_event_register_handler(EV_SES_POST_STARTED, (triton_event_func)ses_started); triton_event_register_handler(EV_SES_ACCT_START, (triton_event_func)ses_acct_start); triton_event_register_handler(EV_SES_FINISHING, (triton_event_func)ses_finishing); triton_event_register_handler(EV_SES_FINISHED, (triton_event_func)ses_finished); diff --git a/accel-pppd/radius/radius_p.h b/accel-pppd/radius/radius_p.h index 35541186..cdbb57b8 100644 --- a/accel-pppd/radius/radius_p.h +++ b/accel-pppd/radius/radius_p.h @@ -43,6 +43,8 @@ struct radius_pd_t { int ipv6_dp_assigned:1; int ipv6_dp_sent:1; + struct rad_packet_t *auth_reply; + struct rad_req_t *acct_req; struct triton_timer_t acct_interim_timer; |