summaryrefslogtreecommitdiff
path: root/accel-pppd/radius
diff options
context:
space:
mode:
authorDmitry Kozlov <xeb@mail.ru>2017-10-17 23:23:54 +0300
committerDmitry Kozlov <xeb@mail.ru>2017-10-17 23:33:44 +0300
commit405a4d8de0048aa77d09380b33a3f06149d16765 (patch)
treed3de19458bb0d17529e6d029f11b4ecefef56fed /accel-pppd/radius
parent0a71249f32169ad04fd6a907989578dced3ba9ec (diff)
downloadaccel-ppp-xebd-405a4d8de0048aa77d09380b33a3f06149d16765.tar.gz
accel-ppp-xebd-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.txt9
-rw-r--r--accel-pppd/radius/auth.c4
-rw-r--r--accel-pppd/radius/lua.c183
-rw-r--r--accel-pppd/radius/radius.c10
-rw-r--r--accel-pppd/radius/radius_p.h2
5 files changed, 207 insertions, 1 deletions
diff --git a/accel-pppd/radius/CMakeLists.txt b/accel-pppd/radius/CMakeLists.txt
index db56b5d..8cb66ce 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 b590002..4cc5ff7 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 0000000..45f7875
--- /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 eede906..b870601 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 3554118..cdbb57b 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;