Creating in C++ Module for FreeRadius
Hello everybody, here are my Steps how i created an C++ Module for FreeRadius. - *Adaptions in the radiusd.conf* Create an new Module Section like: modules { cpp { … } } - Creating an new Directory in the modules Directory I created an new Directory named "*rlm_cpp*" where I putted an Makefile and my *rlm_cpp.cpp* File *Makefile:* *TARGET = rlm_cpp * *SRCS = rlm_cpp.cpp * *HEADERS = RLM_CFLAGS = -I/usr/include RLM_LIBS = -lc RLM_INSTALL = install-example ## this uses the RLM_CFLAGS and RLM_LIBS and SRCS defs to make TARGET. include ../rules.mak $(LT_OBJS): $(HEADERS) ## the rule that RLM_INSTALL tells the parent rules.mak to use. install-example: touch .* My outgoing rlm_cpp.cpp File was the *.c File I took. Then I need to change every function of this file like this: *extern "C"* { static int cpp_authorize(void *instance, REQUEST *request) { ... } } Then I added two DEFINES at the TOP of my rlm_cpp.cpp File, because the two words are reserved names in in C. *#define operator op3578000 #define template tem34123* At the end I needed to change the the struct. First I changed the struct in radiusd.conf struct auth_req { ... home_server*_t * *home_server ... } typedef struct radclient { ... home_server*_t * *coa_server; ... } RADCLIENT; Also change the Typedef to: typedef struct home_server { ... }home_server*_t;* Every struct in the Source of FreeRadius need to be changed to * home_server_t*! now you should made finallay the main make and see the all should be fine compiled! at the end run "make install " and implement the new C++ Module in an Section in the radiusd.conf and it will run! Greetz Patrick
O.K. I'm confused. Last time I checked C++ code needs special initialization at process start. Usually this is done by linking against a different main which causes the C++ run-time to be initialized. When you build a C++ process this happens automatically, but for standard C code it requires forcing the linker to use alternate initialization. You can always call C from C++, but you can't call C++ from a C based process without special linking. How are you handling this? Or is there something special about loading a C++ module which causes the C++ runtime to be initialized? -- John Dennis <jdennis@redhat.com> Looking to carve out IT costs? www.redhat.com/carveoutcosts/
John Dennis wrote:
You can always call C from C++, but you can't call C++ from a C based process without special linking. How are you handling this?
<la la la la>
Or is there something special about loading a C++ module which causes the C++ runtime to be initialized?
No. The server doesn't do C++, and never will. Linus isn't entirely wrong. Alan DeKok.
• Creating an new Directory in the modules Directory I created an new Directory named "rlm_cpp" where I putted an Makefile and my rlm_cpp.cpp File
Makefile:
TARGET = rlm_cpp SRCS = rlm_cpp.cpp HEADERS = RLM_CFLAGS = -I/usr/include RLM_LIBS = -lc RLM_INSTALL = install-example
You have to link to libc explicitly?
My outgoing rlm_cpp.cpp File was the *.c File I took. Then I need to change every function of this file like this:
extern "C" { static int cpp_authorize(void *instance, REQUEST *request) { ... } }
Still not 100% sure whether this is required, my suspicion is that the module will still link and execute, but that it's probably good practice to declare the C linkages explicity. In any case I think you can just do : extern "C" static int cpp_authorize(void *instance, REQUEST *request) { } Looks cleaner.
Then I added two DEFINES at the TOP of my rlm_cpp.cpp File, because the two words are reserved names in in C.
#define operator op3578000 #define template tem34123
You mean in C++, they're not reserved keywords in C. I already changed "op" in master, i'll have a look at template.
At the end I needed to change the the struct. First I changed the struct in radiusd.conf
radiusd.conf is a configuration file...
struct auth_req { ... home_server_t *home_server ... }
typedef struct radclient { ... home_server_t *coa_server; ... } RADCLIENT;
Also change the Typedef to:
typedef struct home_server { ... }home_server_t;
Every struct in the Source of FreeRadius need to be changed to home_server_t!
Does the _t have a special significance in C++ or did you just want to follow convention?
now you should made finallay the main make and see the all should be fine compiled! at the end run "make install " and implement the new C++ Module in an Section in the radiusd.conf and it will run!
Sure. This is nice and all, but if you want your modules in the standard distribution of FreeRADIUS it's probably better to just write them in C. The only exception would be if they dependended on an external library for which there was no C equivalent, or which did not expose a C API (the MySQL ndb client library is like this, which is why i've also been investigating). Interesting all the same. Thanks for posting the info. -Arran
Sorry I needed the libc for some other things ( I also created a new c++-Class which i called inside my Module ) No the _t did not have any special significance in C++ I only followed the convetion! Here also is my rlm_cpp.cpp Module #define operator op3578000 #define template tem34123 extern "C" { #include <freeradius-devel/ident.h> #include <stdio.h> #include <stdlib.h> #include <string.h> RCSID("$Id$") #include <freeradius-devel/radiusd.h> #include <freeradius-devel/modules.h> typedef struct rlm_cpp_t { int boolean; int value; char *string; uint32_t ipaddr; } rlm_cpp_t; extern "C" const CONF_PARSER module_config[] = { { "integer", PW_TYPE_INTEGER, offsetof(rlm_cpp_t,value), NULL, "1" }, { "boolean", PW_TYPE_BOOLEAN, offsetof(rlm_cpp_t,boolean), NULL, "no"}, { "string", PW_TYPE_STRING_PTR, offsetof(rlm_cpp_t,string), NULL, NULL}, { "ipaddr", PW_TYPE_IPADDR, offsetof(rlm_cpp_t,ipaddr), NULL, "*"}, { NULL, -1, 0, NULL, NULL } /* end the list */ }; extern "C" { static int cpp_instantiate(CONF_SECTION *conf, void **instance) { ... return RLM_MODULE_OK; } } extern "C" { static int cpp_post_auth(void *instance, REQUEST *request) { VALUE_PAIR *reply; VALUE_PAIR *state; ... return RLM_MODULE_OK; } } extern "C" { static int cpp_preacct(void *instance, REQUEST *request) { /* quiet the compiler */ instance = instance; request = request; ... return RLM_MODULE_OK; } } extern "C" { static int cpp_authorize(void *instance, REQUEST *request) { /* quiet the compiler */ instance = instance; request = request; ... return RLM_MODULE_OK; } } extern "C" { module_t rlm_cpp = { RLM_MODULE_INIT, "cpp", RLM_TYPE_THREAD_SAFE, /* type */ cpp_instantiate, /* instantiation */ NULL, /* detach */ { NULL, /* authentication */ cpp_authorize, /* authorization */ cpp_preacct, /* preaccounting */ NULL, /* accounting */ NULL, /* checksimul */ NULL, /* pre-proxy */ NULL, /* post-proxy */ cpp_post_auth /* post-auth */ }, }; } 2013/3/11 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
• Creating an new Directory in the modules Directory I created an new Directory named "rlm_cpp" where I putted an
Makefile and my rlm_cpp.cpp File
Makefile:
TARGET = rlm_cpp SRCS = rlm_cpp.cpp HEADERS = RLM_CFLAGS = -I/usr/include RLM_LIBS = -lc RLM_INSTALL = install-example
You have to link to libc explicitly?
My outgoing rlm_cpp.cpp File was the *.c File I took. Then I need to change every function of this file like this:
extern "C" { static int cpp_authorize(void *instance, REQUEST *request) { ... } }
Still not 100% sure whether this is required, my suspicion is that the module will still link and execute, but that it's probably good practice to declare the C linkages explicity.
In any case I think you can just do :
extern "C" static int cpp_authorize(void *instance, REQUEST *request) {
}
Looks cleaner.
Then I added two DEFINES at the TOP of my rlm_cpp.cpp File, because the
two words are reserved names in in C.
#define operator op3578000 #define template tem34123
You mean in C++, they're not reserved keywords in C. I already changed "op" in master, i'll have a look at template.
At the end I needed to change the the struct. First I changed the struct in radiusd.conf
radiusd.conf is a configuration file...
struct auth_req { ... home_server_t *home_server ... }
typedef struct radclient { ... home_server_t *coa_server; ... } RADCLIENT;
Also change the Typedef to:
typedef struct home_server { ... }home_server_t;
Every struct in the Source of FreeRadius need to be changed to home_server_t!
Does the _t have a special significance in C++ or did you just want to follow convention?
now you should made finallay the main make and see the all should be fine compiled! at the end run "make install " and implement the new C++ Module in an Section in the radiusd.conf and it will run!
Sure. This is nice and all, but if you want your modules in the standard distribution of FreeRADIUS it's probably better to just write them in C. The only exception would be if they dependended on an external library for which there was no C equivalent, or which did not expose a C API (the MySQL ndb client library is like this, which is why i've also been investigating).
Interesting all the same. Thanks for posting the info.
-Arran - List info/subscribe/unsubscribe? See http://www.freeradius.org/list/devel.html
Some time ago I wrote C++ module for freeradius (to interact with billing interface) with next approach: 1. write special c file where freeradius API is imported, and API which is callable from "C++" for access to radius struct 2. and special .h "freeradius_cpp_api.h" file where prototypes with this "accessors from C++" is defined with external "C" linkage. 3. import in c++ "freeradius_cpp_api.h" instead freeradius headers. and at least with gcc - all works fine after linking with right libraries. On Mon, Mar 11, 2013 at 3:58 PM, Patrick Ko <patrick0585@googlemail.com>wrote:
Hello everybody, here are my Steps how i created an C++ Module for FreeRadius.
- *Adaptions in the radiusd.conf*
Create an new Module Section like:
modules {
cpp {
…
}
}
- Creating an new Directory in the modules Directory
I created an new Directory named "*rlm_cpp*" where I putted an Makefile and my *rlm_cpp.cpp* File
*Makefile:*
*TARGET = rlm_cpp * *SRCS = rlm_cpp.cpp * *HEADERS = RLM_CFLAGS = -I/usr/include RLM_LIBS = -lc RLM_INSTALL = install-example
## this uses the RLM_CFLAGS and RLM_LIBS and SRCS defs to make TARGET. include ../rules.mak
$(LT_OBJS): $(HEADERS)
## the rule that RLM_INSTALL tells the parent rules.mak to use. install-example: touch .*
My outgoing rlm_cpp.cpp File was the *.c File I took. Then I need to change every function of this file like this:
*extern "C"* { static int cpp_authorize(void *instance, REQUEST *request) { ... } }
Then I added two DEFINES at the TOP of my rlm_cpp.cpp File, because the two words are reserved names in in C.
*#define operator op3578000 #define template tem34123*
At the end I needed to change the the struct. First I changed the struct in radiusd.conf
struct auth_req { ... home_server*_t * *home_server ... }
typedef struct radclient { ... home_server*_t * *coa_server; ... } RADCLIENT;
Also change the Typedef to:
typedef struct home_server { ... }home_server*_t;*
Every struct in the Source of FreeRadius need to be changed to * home_server_t*!
now you should made finallay the main make and see the all should be fine compiled! at the end run "make install " and implement the new C++ Module in an Section in the radiusd.conf and it will run!
Greetz Patrick
- List info/subscribe/unsubscribe? See http://www.freeradius.org/list/devel.html
-- Ruslan Shevchenko Software Engineer. http://ua.linkedin.com/in/ruslanshevchenko
Hello Ruslan Shevchenko, I you have created an C++ Module for FreeRadius, maybe you could post it ? Greetz Patrick Am 11.03.13 16:35, schrieb Ruslan Shevchenko:
Some time ago I wrote C++ module for freeradius (to interact with billing interface) with next approach:
1. write special c file where freeradius API is imported, and API which is callable from "C++" for access to radius struct
2. and special .h "freeradius_cpp_api.h" file where prototypes with this "accessors from C++" is defined with external "C" linkage.
3. import in c++ "freeradius_cpp_api.h" instead freeradius headers.
and at least with gcc - all works fine after linking with right libraries.
On Mon, Mar 11, 2013 at 3:58 PM, Patrick Ko <patrick0585@googlemail.com <mailto:patrick0585@googlemail.com>> wrote:
Hello everybody, here are my Steps how i created an C++ Module for FreeRadius.
* *Adaptions in the radiusd.conf*
Create an new Module Section like:
modules {
cpp {
...
}
}
* Creating an new Directory in the modules Directory
I created an new Directory named "*rlm_cpp*" where I putted an Makefile and my *rlm_cpp.cpp* File
*Makefile:*
/TARGET = rlm_cpp / /SRCS = rlm_cpp.cpp / /HEADERS = RLM_CFLAGS = -I/usr/include RLM_LIBS = -lc RLM_INSTALL = install-example
## this uses the RLM_CFLAGS and RLM_LIBS and SRCS defs to make TARGET. include ../rules.mak
$(LT_OBJS): $(HEADERS)
## the rule that RLM_INSTALL tells the parent rules.mak to use. install-example: touch ./
My outgoing rlm_cpp.cpp File was the *.c File I took. Then I need to change every function of this file like this:
*extern "C"* { static int cpp_authorize(void *instance, REQUEST *request) { ... } }
Then I added two DEFINES at the TOP of my rlm_cpp.cpp File, because the two words are reserved names in in C.
*#define operator op3578000 #define template tem34123*
At the end I needed to change the the struct. First I changed the struct in radiusd.conf
struct auth_req { ... home_server*_t * *home_server ... }
typedef struct radclient { ... home_server*_t * *coa_server; ... } RADCLIENT;
Also change the Typedef to:
typedef struct home_server { ... }home_server*_t;*
Every struct in the Source of FreeRadius need to be changed to *home_server_t*!
now you should made finallay the main make and see the all should be fine compiled! at the end run "make install " and implement the new C++ Module in an Section in the radiusd.conf and it will run!
Greetz Patrick
- List info/subscribe/unsubscribe? See http://www.freeradius.org/list/devel.html
-- Ruslan Shevchenko Software Engineer. http://ua.linkedin.com/in/ruslanshevchenko
- List info/subscribe/unsubscribe? See http://www.freeradius.org/list/devel.html
participants (6)
-
Alan DeKok -
Arran Cudbard-Bell -
John Dennis -
Patrick Ko -
Patrick Kowalik -
Ruslan Shevchenko