Wednesday, January 5, 2011

FreeRADIUS with Oracle

Recently working on FreeRADIUS Sever v2.1.10, I found that there are some problems in making FreeRADIUS to work with Oracle. I had the same problem described at here. Following is the problem statement put by Alexandre, at the above link: (Great work Alexandre!!)


Unless I missunderstood the compil process it seems to me that todays source tree is stuck to Oracle 10g. Indeed the configure.in file for the rlm_sql_oracle module has a library name harcoded: libnnz10.
If you run Oracle instantclient 11g (I guess it's the same with a full installation of Oracle 11g) the library is named libnnz11. As a result, oracle linking test wiil always fail even with a correct --with-oracle-lib-dir set.
To be able to compile with both version of Oracle (10g and 11g)
I suggest a new option can be set that would define the version during ./configure.
If it sounds ok for everyone and can be tested by more people (I only tested it on Debian with instantclient_11.1), here is "works for me" patch that introduce the --with-oracle-version switch.
As Alexandre rightly guessed, there exists the same problem with full installation of Oracle 11g. However I reckon there shouldn’t be any problem with Oracle Instant Client 10g or Full Oracle installation of 10g when being configured with FreeRADIUS v2.1.10 and v2.1.9.


Although, required changes have been mentioned at the above link, I am going to provide the complete file here, so you don’t have to make the changes yourself and everything is in place before you start installing FreeRADIUS. This will work for 10g and 11g both instant client and full installation. By the way, I have tried this on Red Hat and CentOS 5. While trying on CentOS, I was trying to install FreeRADIUS Sever v2.1.9 with full Oracle 11g Installation and was struck with the same problem.


Once you have downloaded and untarred the FreeRADIUS tar file. (My untarred FreeRADIUS directory is in /usr/local/src i.e. /usr/local/src/freeradius-server-2.1.10). In this directory, go to ./src/modules/rlm_sql/drivers/rlm_sql_oracle directory. So the complete path becomes /usr/local/src/freeradius-server-2.1.10/src/modules/rlm_sql/drivers/rlm_sql_oracle. Replace the contents of ‘configure.in’ file with the contents I have provided here. (I can upload this file to some location if you need it and if you let me know some place)


AC_INIT(sql_oracle.c)
AC_REVISION($Revision: 1.10 $)
AC_DEFUN(modname,[rlm_sql_oracle])

fail=
sql_oracle_ldflags=
sql_oracle_cflags=
if test x$with_[]modname != xno; then

AC_MSG_CHECKING([for oci.h])

dnl #
dnl # See if the user passed in the oracle_home_dir option and
dnl # use that first. If not, use $ORACLE_HOME. If that's
dnl # not defined, give up. There's no point in blindly
dnl # hunting around for Oracle - there's no standard place
dnl # for it. Any sane Oracle user/developer should have $ORACLE_HOME
dnl # defined anyways.
dnl #

dnl ############################################################
dnl # Check for command line options
dnl ############################################################


dnl extra argument: --with-oracle-version=VER
oracle_version=
AC_ARG_WITH(oracle-version,
[AS_HELP_STRING([--with-oracle-version=VER],
[Version of Oracle to search for. Should be 10 for Oracle 10g and 11 for 11g])],
[case "$withval" in
11)
oracle_version="$withval"
;;
10)
oracle_version="$withval"
;;
*)
AC_MSG_ERROR(Need oracle-version)
;;
esac])

dnl extra argument: --with-oracle-include-dir=DIR
oracle_include_dir=
AC_ARG_WITH(oracle-include-dir,
[AS_HELP_STRING([--with-oracle-include-dir=DIR],
[Directory where the Oracle includes may be found. It should be located under ORACLE_HOME if you have client SDK installed. Use --with-oracle-include-dir=yes if you are sure that your compiler include path includes Oracle include dir. Hint: you might try to do: locate oci.h])],
[case "$withval" in
no)
AC_MSG_ERROR(Need oracle-include-dir)
;;
yes)
;;
*)
oracle_include_dir="$withval"
;;
esac])

dnl extra argument: --with-oracle-lib-dir=DIR
oracle_lib_dir=
AC_ARG_WITH(oracle-lib-dir,
[AS_HELP_STRING([--with-oracle-lib-dir=DIR],
[Directory where the oracle libraries may be found. It should be located under ORACLE_HOME. iUse --with-oracle-lib-dir=yes if you are sure that your linker will find the necessary Oracle client libs. Hint: you might try to do: locate libclntsh.so])],
[case "$withval" in
no)
AC_MSG_ERROR(Need oracle-lib-dir)
;;
yes)
;;
*)
oracle_lib_dir="$withval"
;;
esac])



AC_TRY_COMPILE([#include ],
[ int a = 1;],
ORACLE_INCLUDE=" ",
ORACLE_INCLUDE=
)

RLM_SQL_ORA_WORKING_CFLAGS_FOR_LINKING_TEST=
if test "x$ORACLE_INCLUDE" = "x" ; then
old_CFLAGS="$CFLAGS"
CFLAGS="$old_CFLAGS -I$oracle_include_dir"
AC_TRY_COMPILE([#include ],
[ int a = 1;],
ORACLE_INCLUDE="-I$oracle_include_dir",
ORACLE_INCLUDE=
)

RLM_SQL_ORA_WORKING_CFLAGS_FOR_LINKING_TEST="$CFLAGS"
CFLAGS="$old_CFLAGS"
fi

# Proceed to linking makes only sense if include dir is OK.
if test "x$ORACLE_INCLUDE" != "x" ; then
old_LIBS="$LIBS"
old_CFLAGS="$CFLAGS"
CFLAGS="$RLM_SQL_ORA_WORKING_CFLAGS_FOR_LINKING_TEST"

ORACLE_LIBDIR_SWITCH=
if test "x$oracle_lib_dir" != "x" ; then
ORACLE_LIBDIR_SWITCH="-L${oracle_lib_dir} "
fi
if test "x$oracle_version" = "x" ; then
AC_MSG_RESULT(no)
AC_MSG_WARN([oracle version not found. Use --with-oracle-version={10|11}.])
fail="$fail Oracle version"
else
LIBS="$old_LIBS $ORACLE_LIBDIR_SWITCH -lclntsh -lnnz${oracle_version}"

AC_TRY_LINK([#include

static OCIEnv *p_env;
static OCIError *p_err;
static OCISvcCtx *p_svc;
static OCIStmt *p_sql;
static OCIDefine *p_dfn = (OCIDefine *) 0;
static OCIBind *p_bnd = (OCIBind *) 0;
],
[
int p_bvi;
char p_sli[20];
int rc;
char errbuf[100];
int errcode;

rc = OCIInitialize((ub4) OCI_DEFAULT, (dvoid *)0, /* Initialize OCI */
(dvoid * (*)(dvoid *, size_t)) 0,
(dvoid * (*)(dvoid *, dvoid *, size_t))0,
(void (*)(dvoid *, dvoid *)) 0 );

],
ORACLE_LIBS="$ORACLE_LIBDIR_SWITCH -lclntsh -lnnz${oracle_version}",
ORACLE_LIBS=
)

LIBS="$old_LIBS"
CFLAGS="$old_CFLAGS"
fi
fi


if test "x$ORACLE_INCLUDE" = "x"; then
AC_MSG_RESULT(no)
AC_MSG_WARN([oracle headers not found. Use --with-oracle-include-dir=.])
fail="$fail oci.h"
else
sql_oracle_cflags="${sql_oracle_cflags} ${ORACLE_INCLUDE}"
AC_MSG_RESULT(yes)


if test "x$ORACLE_LIBS" = "x"; then
AC_MSG_WARN([oracle libraries not found. Use --with-oracle-lib-dir=.])
fail="$fail libclntsh libnnz${oracle_version}"
else
sql_oracle_ldflags="${sql_oracle_ldflags} $ORACLE_LIBS"
AC_MSG_RESULT(yes)
fi
fi

targetname=modname
else
targetname=
echo \*\*\* module modname is disabled.
fi

dnl Don't change this section.
if test "x$fail" != x; then
if test "x${enable_strict_dependencies}" = xyes; then
AC_MSG_ERROR([set --without-]modname[ to disable it explicitly.])
else
AC_MSG_WARN([silently not building ]modname[.])
AC_MSG_WARN([FAILURE: ]modname[ requires:$fail.]);
targetname=
fi
fi

AC_SUBST(sql_oracle_ldflags)
AC_SUBST(sql_oracle_cflags)
AC_SUBST(targetname)
AC_OUTPUT(Makefile)



FreeRADIUS needs some library and header files to be integrated with Oracle, these files are shipped with Oracle Instant Client and Oracle Full Package both. You can tell FreeRADIUS where to find these files either by setting some system variables before executing the configure script or by passing some arguments to the configure script. We will stick to the second option here.


On my system, I had Oracle Instant Client (both Basic and SDK Packages) unzipped in /opt/instantclient/ so all of my references to Oracle are based on this path.

Now go back to FreeRADIUS’s untarred directory i.e. /usr/local/src/freeradius-server-2.1.10. Now you can run configure script from here by executing following command.


./configure --with-oracle-version=VER --with-oracle-include-dir=DIR --with-oracle-lib-dir=DIR


On my system this command takes the following form having instant client 11g on the path /opt/instantclient/.


./configure --with-oracle-version=11 --with-oracle-include-dir=/opt/instantclient/sdk/include/ --with-oracle-lib-dir=/opt/instantclient/


On a system with full Oracle 11g Installation, I had to execute the following command.


./configure --with-oracle-version=11 --with-oracle-include-dir=/u01/app/oracle/product/11.2.0/dbhome_1/rdbms/public/ --with-oracle-lib-dir=/u01/app/oracle/product/11.2.0/dbhome_1/lib/


Note: If you are using Instant Client or full Oracle 10g, you don’t have to replace the above ini file nor do you need to send the argument --with-oracle-version=VER to the configure script.


Rest of the commands for FreeRADIUS is quite common as below:

make

make install


I hope this post is helpful to those who are facing this problem.



2 comments:

Unknown said...

Hi!

I used this tutorial, tnq! This really helped. I want add that i used such configure string:
./configure --with-oracle-version=11 --with-oracle-include-dir=/usr/include/oracle/11.2/client64/ --with-oracle-lib-dir=/usr/lib/oracle/11.2/client64/lib/
(i used 11.2 instant client)
but this didn't work until i changed in
./src/modules/rlm_sql/drivers/rlm_sql_oracle/configure

all entries "nnz10" to "nnz11" (%s/nnz10/nnz11/g)

Atif said...

FreeRADIUS Book by Pactk Publishing. I contributed as reviewer. Click here to look inside the book