Merge branch 'sam'
authorKevin <kevin@debian.suchdamage.org>
Sat, 4 Feb 2012 02:57:21 +0000 (21:57 -0500)
committerKevin <kevin@debian.suchdamage.org>
Sat, 4 Feb 2012 02:57:21 +0000 (21:57 -0500)
237 files changed:
Make.inc.in
Makefile
configure
configure.in
debian/freeradius.default [new file with mode: 0644]
debian/freeradius.init
debian/freeradius.install
debian/patches/rlm_sql.libs.diff
debian/patches/sql_modules.diff [new file with mode: 0644]
doc/ChangeLog
main.mk [new file with mode: 0644]
man/man1/radwho.1
raddb/Makefile
raddb/README [new file with mode: 0644]
raddb/dictionary.in
raddb/mods-available/acct_unique [moved from raddb/modules/acct_unique with 100% similarity]
raddb/mods-available/always [moved from raddb/modules/always with 100% similarity]
raddb/mods-available/attr_filter [moved from raddb/modules/attr_filter with 100% similarity]
raddb/mods-available/attr_rewrite [moved from raddb/modules/attr_rewrite with 100% similarity]
raddb/mods-available/chap [moved from raddb/modules/chap with 100% similarity]
raddb/mods-available/checkval [moved from raddb/modules/checkval with 100% similarity]
raddb/mods-available/counter [moved from raddb/modules/counter with 100% similarity]
raddb/mods-available/cui [moved from raddb/modules/cui with 100% similarity]
raddb/mods-available/detail [moved from raddb/modules/detail with 93% similarity]
raddb/mods-available/detail.example.com [moved from raddb/modules/detail.example.com with 100% similarity]
raddb/mods-available/detail.log [moved from raddb/modules/detail.log with 100% similarity]
raddb/mods-available/dhcp_sqlippool [new file with mode: 0644]
raddb/mods-available/digest [moved from raddb/modules/digest with 100% similarity]
raddb/mods-available/dynamic_clients [moved from raddb/modules/dynamic_clients with 100% similarity]
raddb/mods-available/eap [moved from raddb/modules/eap with 90% similarity]
raddb/mods-available/echo [moved from raddb/modules/echo with 100% similarity]
raddb/mods-available/etc_group [moved from raddb/modules/etc_group with 100% similarity]
raddb/mods-available/exec [moved from raddb/modules/exec with 100% similarity]
raddb/mods-available/expiration [moved from raddb/modules/expiration with 100% similarity]
raddb/mods-available/expr [moved from raddb/modules/expr with 100% similarity]
raddb/mods-available/files [moved from raddb/modules/files with 100% similarity]
raddb/mods-available/inner-eap [moved from raddb/modules/inner-eap with 100% similarity]
raddb/mods-available/ippool [moved from raddb/modules/ippool with 100% similarity]
raddb/mods-available/krb5 [moved from raddb/modules/krb5 with 100% similarity]
raddb/mods-available/ldap [moved from raddb/modules/ldap with 100% similarity]
raddb/mods-available/linelog [moved from raddb/modules/linelog with 93% similarity]
raddb/mods-available/logintime [moved from raddb/modules/logintime with 100% similarity]
raddb/mods-available/mac2ip [moved from raddb/modules/mac2ip with 100% similarity]
raddb/mods-available/mac2vlan [moved from raddb/modules/mac2vlan with 100% similarity]
raddb/mods-available/mschap [moved from raddb/modules/mschap with 100% similarity]
raddb/mods-available/ntlm_auth [moved from raddb/modules/ntlm_auth with 100% similarity]
raddb/mods-available/opendirectory [moved from raddb/modules/opendirectory with 100% similarity]
raddb/mods-available/otp [moved from raddb/modules/otp with 100% similarity]
raddb/mods-available/pam [moved from raddb/modules/pam with 100% similarity]
raddb/mods-available/pap [moved from raddb/modules/pap with 100% similarity]
raddb/mods-available/passwd [moved from raddb/modules/passwd with 80% similarity]
raddb/mods-available/perl [moved from raddb/modules/perl with 100% similarity]
raddb/mods-available/policy [moved from raddb/modules/policy with 100% similarity]
raddb/mods-available/preprocess [moved from raddb/modules/preprocess with 100% similarity]
raddb/mods-available/radutmp [moved from raddb/modules/radutmp with 100% similarity]
raddb/mods-available/realm [moved from raddb/modules/realm with 100% similarity]
raddb/mods-available/redis [moved from raddb/modules/redis with 100% similarity]
raddb/mods-available/rediswho [moved from raddb/modules/rediswho with 100% similarity]
raddb/mods-available/replicate [moved from raddb/modules/replicate with 100% similarity]
raddb/mods-available/smbpasswd [moved from raddb/modules/smbpasswd with 100% similarity]
raddb/mods-available/smsotp [moved from raddb/modules/smsotp with 100% similarity]
raddb/mods-available/soh [moved from raddb/modules/soh with 100% similarity]
raddb/mods-available/sql [moved from raddb/modules/sql with 80% similarity]
raddb/mods-available/sql_log [moved from raddb/modules/sql_log with 100% similarity]
raddb/mods-available/sqlcounter_expire_on_login [moved from raddb/modules/sqlcounter_expire_on_login with 100% similarity]
raddb/mods-available/sqlippool [moved from raddb/modules/sqlippool with 100% similarity]
raddb/mods-available/sradutmp [moved from raddb/modules/sradutmp with 100% similarity]
raddb/mods-available/unix [moved from raddb/modules/unix with 100% similarity]
raddb/mods-available/utf8 [moved from raddb/modules/utf8 with 100% similarity]
raddb/mods-available/wimax [moved from raddb/modules/wimax with 100% similarity]
raddb/policy.conf
raddb/radiusd.conf.in
raddb/sites-available/chbind [new file with mode: 0644]
raddb/sites-available/dhcp
raddb/sql/mysql/ippool-dhcp.conf [new file with mode: 0644]
redhat/freeradius.spec
scripts/boiler.mk [new file with mode: 0644]
scripts/install.mk [new file with mode: 0644]
scripts/jlibtool.c [new file with mode: 0644]
scripts/libtool.mk [new file with mode: 0644]
scripts/main.mk [new file with mode: 0644]
share/dictionary
share/dictionary.manzara
share/dictionary.rfc5447 [new file with mode: 0644]
src/Makefile
src/all.mk [new file with mode: 0644]
src/include/all.mk [new file with mode: 0644]
src/include/libradius.h
src/include/modpriv.h
src/include/packet.h
src/include/radius.h
src/include/tls.h
src/lib/all.mk [new file with mode: 0644]
src/lib/dhcp.c
src/lib/dict.c
src/lib/packet.c
src/lib/radius.c
src/main/Makefile.in
src/main/acct.c
src/main/all.mk [new file with mode: 0644]
src/main/auth.c
src/main/exec.c
src/main/listen.c
src/main/log.c
src/main/mainconfig.c
src/main/modules.c
src/main/process.c
src/main/radclient.mk [new file with mode: 0644]
src/main/radconf2xml.c
src/main/radiusd.c
src/main/radiusd.mk [new file with mode: 0644]
src/main/radsniff.c
src/main/radsniff.mk.in [new file with mode: 0644]
src/main/radwho.c
src/main/realms.c
src/main/threads.c
src/main/tls.c
src/main/tls_listen.c [new file with mode: 0644]
src/main/util.c
src/modules/all.mk [new file with mode: 0644]
src/modules/rlm_acct_unique/all.mk [new file with mode: 0644]
src/modules/rlm_acctlog/all.mk [new file with mode: 0644]
src/modules/rlm_always/all.mk [new file with mode: 0644]
src/modules/rlm_attr_filter/all.mk [new file with mode: 0644]
src/modules/rlm_attr_rewrite/all.mk [new file with mode: 0644]
src/modules/rlm_chap/all.mk [new file with mode: 0644]
src/modules/rlm_checkval/all.mk [new file with mode: 0644]
src/modules/rlm_copy_packet/all.mk [new file with mode: 0644]
src/modules/rlm_counter/all.mk [new file with mode: 0644]
src/modules/rlm_cram/all.mk [new file with mode: 0644]
src/modules/rlm_dbm/Makefile.in
src/modules/rlm_dbm/all.mk [new file with mode: 0644]
src/modules/rlm_dbm/rlm_dbm_parser.8 [moved from src/modules/rlm_dbm/rlm_dbm_parse.8 with 91% similarity]
src/modules/rlm_detail/all.mk [new file with mode: 0644]
src/modules/rlm_detail/rlm_detail.c
src/modules/rlm_digest/all.mk [new file with mode: 0644]
src/modules/rlm_dynamic_clients/all.mk [new file with mode: 0644]
src/modules/rlm_eap/Makefile.in
src/modules/rlm_eap/all.mk [new file with mode: 0644]
src/modules/rlm_eap/libeap/all.mk [new file with mode: 0644]
src/modules/rlm_eap/libeap/eap_types.h
src/modules/rlm_eap/libeap/eapcommon.c
src/modules/rlm_eap/radeapclient.c
src/modules/rlm_eap/radeapclient.mk [new file with mode: 0644]
src/modules/rlm_eap/rlm_eap.mk [new file with mode: 0644]
src/modules/rlm_eap/types/all.mk [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_gtc/Makefile
src/modules/rlm_eap/types/rlm_eap_gtc/all.mk [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_ikev2/Makefile.in
src/modules/rlm_eap/types/rlm_eap_leap/Makefile
src/modules/rlm_eap/types/rlm_eap_leap/all.mk [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_md5/Makefile
src/modules/rlm_eap/types/rlm_eap_md5/all.mk [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_mschapv2/Makefile
src/modules/rlm_eap/types/rlm_eap_mschapv2/all.mk [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_mschapv2/rlm_eap_mschapv2.c
src/modules/rlm_eap/types/rlm_eap_peap/Makefile.in
src/modules/rlm_eap/types/rlm_eap_peap/all.mk [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_peap/peap.c
src/modules/rlm_eap/types/rlm_eap_sim/Makefile
src/modules/rlm_eap/types/rlm_eap_tls/Makefile.in
src/modules/rlm_eap/types/rlm_eap_tls/all.mk [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c
src/modules/rlm_eap/types/rlm_eap_tnc/Makefile.in
src/modules/rlm_eap/types/rlm_eap_ttls/Makefile.in
src/modules/rlm_eap/types/rlm_eap_ttls/all.mk [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c
src/modules/rlm_eap2/Makefile
src/modules/rlm_eap2/all.mk [new file with mode: 0644]
src/modules/rlm_exec/all.mk [new file with mode: 0644]
src/modules/rlm_expiration/all.mk [new file with mode: 0644]
src/modules/rlm_expr/all.mk [new file with mode: 0644]
src/modules/rlm_expr/rlm_expr.c
src/modules/rlm_fastusers/all.mk [new file with mode: 0644]
src/modules/rlm_files/all.mk [new file with mode: 0644]
src/modules/rlm_ippool/Makefile.in
src/modules/rlm_ippool/all.mk [new file with mode: 0644]
src/modules/rlm_jradius/all.mk [new file with mode: 0644]
src/modules/rlm_krb5/all.mk.in [new file with mode: 0644]
src/modules/rlm_krb5/configure
src/modules/rlm_krb5/configure.in
src/modules/rlm_ldap/all.mk.in [new file with mode: 0644]
src/modules/rlm_ldap/configure
src/modules/rlm_ldap/configure.in
src/modules/rlm_linelog/all.mk [new file with mode: 0644]
src/modules/rlm_linelog/rlm_linelog.c
src/modules/rlm_logintime/all.mk [new file with mode: 0644]
src/modules/rlm_mschap/Makefile
src/modules/rlm_mschap/all.mk [new file with mode: 0644]
src/modules/rlm_mschap/mschap.c
src/modules/rlm_mschap/rlm_mschap.mk [new file with mode: 0644]
src/modules/rlm_mschap/smbencrypt.mk [new file with mode: 0644]
src/modules/rlm_otp/all.mk [new file with mode: 0644]
src/modules/rlm_pam/all.mk.in [new file with mode: 0644]
src/modules/rlm_pam/configure
src/modules/rlm_pam/configure.in
src/modules/rlm_pap/all.mk [new file with mode: 0644]
src/modules/rlm_passwd/all.mk [new file with mode: 0644]
src/modules/rlm_passwd/rlm_passwd.c
src/modules/rlm_perl/all.mk.in [new file with mode: 0644]
src/modules/rlm_perl/configure
src/modules/rlm_perl/configure.in
src/modules/rlm_policy/all.mk [new file with mode: 0644]
src/modules/rlm_policy/evaluate.c
src/modules/rlm_policy/parse.c
src/modules/rlm_preprocess/all.mk [new file with mode: 0644]
src/modules/rlm_preprocess/rlm_preprocess.c
src/modules/rlm_python/all.mk.in [new file with mode: 0644]
src/modules/rlm_python/configure
src/modules/rlm_python/configure.in
src/modules/rlm_radutmp/all.mk [new file with mode: 0644]
src/modules/rlm_realm/all.mk [new file with mode: 0644]
src/modules/rlm_rediswho/Makefile.in
src/modules/rlm_sim_files/all.mk [new file with mode: 0644]
src/modules/rlm_sql/Makefile.in
src/modules/rlm_sql/all.mk [new file with mode: 0644]
src/modules/rlm_sql/drivers/rlm_sql_db2/Makefile.in
src/modules/rlm_sql/drivers/rlm_sql_firebird/Makefile.in
src/modules/rlm_sql/drivers/rlm_sql_iodbc/Makefile.in
src/modules/rlm_sql/drivers/rlm_sql_mysql/Makefile.in
src/modules/rlm_sql/drivers/rlm_sql_mysql/sql_mysql.c
src/modules/rlm_sql/drivers/rlm_sql_oracle/Makefile.in
src/modules/rlm_sql/drivers/rlm_sql_postgresql/Makefile.in
src/modules/rlm_sql/drivers/rlm_sql_sqlite/Makefile.in
src/modules/rlm_sql/drivers/rlm_sql_sybase/Makefile
src/modules/rlm_sql/drivers/rlm_sql_unixodbc/Makefile.in
src/modules/rlm_sql_log/all.mk [new file with mode: 0644]
src/modules/rlm_sql_log/rlm_sql_log.c
src/modules/rlm_sqlcounter/all.mk [new file with mode: 0644]
src/modules/rlm_sqlhpwippool/Makefile.in
src/modules/rlm_sqlippool/Makefile.in
src/modules/rlm_sqlippool/all.mk [new file with mode: 0644]
src/modules/rlm_unix/all.mk [new file with mode: 0644]
src/modules/rlm_unix/rlm_unix.c
src/modules/rlm_wimax/Makefile [deleted file]
src/modules/rlm_wimax/all.mk [new file with mode: 0644]
src/modules/rules.mak

index 1e11dc9..768c541 100644 (file)
@@ -58,6 +58,7 @@ LIBRADIUS     = $(top_builddir)/src/lib/$(LIBPREFIX)freeradius-radius.la
 LIBLTDL                = @LIBLTDL@
 INCLTDL                = @INCLTDL@
 LTDL_SUBDIRS   = @LTDL_SUBDIRS@
+CFLAGS         += $(INCLTDL)
 
 USE_SHARED_LIBS        = @USE_SHARED_LIBS@
 USE_STATIC_LIBS = @USE_STATIC_LIBS@
index 6750ff4..adb4c2d 100644 (file)
--- a/Makefile
+++ b/Makefile
 include Make.inc
 MFLAGS += --no-print-directory
 
+# Speed up the build for developers.  This means editing Make.inc,
+# and adding "BOILER = yes" to the bottom.  Once that's done, the
+#
+#
+ifeq "$(BOILER)" "yes"
+
+# Require at least GNU Make 3.81 for the new build system
+# Don't allow 3.80.  Allow any 3.8x.  This will need to be changed
+# in a decade or two when GNU Make 3.90 is released.
+BOILERMAKE=$(subst 3.8,yes,$(subst 3.80,,$(MAKE_VERSION)))
+
+# The version of GNU Make is too old, don't use it.
+ifeq "" "$(findstring yes,$(BOILERMAKE))"
+BOILERMAKE=
+endif
+
+# Static-only builds still require libtool.
+# This is because it does all kinds of preload magic in order
+# to force the linker to put the libraries into the main binary.
+# We don't support that yet, so we miss it...
+ifneq "$(USE_SHARED_LIBS)" "yes"
+BOILERMAKE=
+endif
+endif
+
+# If possible, drastically decrease the build time.
+# The new build system means that 
+ifneq "" "$(BOILERMAKE)"
+
+# Don't use libtool or libltdl.
+# They are a blight upon the face of the earth.
+LIBLTDL                :=
+INCLTDL                := -DWITH_DLOPEN
+CFLAGS         += -DWITHOUT_LIBLTDL
+LIBTOOL                := JLIBTOOL
+LTDL_SUBDIRS   :=
+
+export DESTDIR := $(R)
+
+# And over-ride all of the other magic.
+include scripts/boiler.mk
+
+else
 .PHONY: all clean install
 
 SUBDIRS                = $(LTDL_SUBDIRS) $(wildcard src raddb scripts doc)
@@ -21,6 +64,7 @@ all:
 clean:
        @$(MAKE) $(MFLAGS) WHAT_TO_MAKE=$@ common
        @rm -f *~
+endif
 
 .PHONY: tests
 tests:
@@ -44,6 +88,7 @@ tests:
 # we make sure DESTDIR is defined.
 #
 export DESTDIR := $(R)
+ifeq "$(BOILERMAKE)" ""
 install:
        $(INSTALL) -d -m 755    $(R)$(sbindir)
        $(INSTALL) -d -m 755    $(R)$(bindir)
@@ -67,6 +112,7 @@ install:
                $(INSTALL) -m 644 $$i $(R)$(dictdir); \
        done
        $(LIBTOOL) --finish $(R)$(libdir)
+endif
 
 ifneq ($(RADMIN),)
 ifneq ($(RGROUP),)
index 941b22a..022ad9d 100755 (executable)
--- a/configure
+++ b/configure
@@ -1489,7 +1489,7 @@ Optional Packages:
   --with-ascend-binary    Include support for Ascend binary filter attributes (default=yes)
   --with-threads          Use threads, if available.  (default=yes)
   --with-vmps             Compile in VMPS support. (default=yes)
-  --with-dhcp             Compile in DHCP support. (default=no)
+  --with-dhcp             Compile in DHCP support. (default=yes)
   --with-static-modules=QUOTED-MODULE-LIST
  --with-modules=QUOTED-MODULE-LIST
   --with-experimental-modules      Use experimental and unstable modules. (default=no)
@@ -20303,25 +20303,31 @@ _ACEOF
 
 fi
 
+WITH_DHCP=yes
 
 # Check whether --with-dhcp was given.
 if test "${with_dhcp+set}" = set; then
   withval=$with_dhcp;  case "$withval" in
     yes)
+        ;;
+    *)
+       WITH_DHCP=no
+  esac
+
+fi
+
+if test "x$WITH_DHCP" = "xyes"; then
 
 cat >>confdefs.h <<\_ACEOF
 #define WITH_DHCP 1
 _ACEOF
 
-       ;;
-    *)
-       ;;
-  esac
-
 fi
 
 
 
+
+
 STATIC_MODULES=
 
 # Check whether --with-static_modules was given.
@@ -26177,7 +26183,7 @@ USE_STATIC_LIBS=$enable_static
   unset ac_cv_env_LIBS_set
   unset ac_cv_env_LIBS_value
 
-  ac_config_files="$ac_config_files ./Make.inc ./src/include/build-radpaths-h ./src/main/Makefile ./src/main/checkrad.pl ./src/main/radlast ./src/main/radtest ./scripts/rc.radiusd ./scripts/radwatch ./scripts/radiusd.cron.daily ./scripts/radiusd.cron.monthly ./scripts/cryptpasswd ./raddb/dictionary ./raddb/radrelay.conf ./raddb/radiusd.conf"
+  ac_config_files="$ac_config_files ./Make.inc ./src/include/build-radpaths-h ./src/main/Makefile ./src/main/radsniff.mk ./src/main/checkrad.pl ./src/main/radlast ./src/main/radtest ./scripts/rc.radiusd ./scripts/radwatch ./scripts/radiusd.cron.daily ./scripts/radiusd.cron.monthly ./scripts/cryptpasswd ./raddb/dictionary ./raddb/radrelay.conf ./raddb/radiusd.conf"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
index 18a97ae..eace2ee 100644 (file)
@@ -259,16 +259,19 @@ if test "x$WITH_VMPS" = "xyes"; then
 fi
 
 dnl extra argument: --with-dhcp
+WITH_DHCP=yes
 AC_ARG_WITH(dhcp,
-[  --with-dhcp             Compile in DHCP support. (default=no)],
+[  --with-dhcp             Compile in DHCP support. (default=yes)],
 [ case "$withval" in
     yes)
-        AC_DEFINE(WITH_DHCP, [1], [Include experimental support for DHCP])
-       ;;
+        ;;
     *)
-       ;;
+       WITH_DHCP=no
   esac ]
 )
+if test "x$WITH_DHCP" = "xyes"; then
+       AC_DEFINE(WITH_DHCP, [1], [define if you want DHCP support])
+fi
 
 
 dnl #
@@ -1220,6 +1223,7 @@ AC_OUTPUT(\
        ./Make.inc \
        ./src/include/build-radpaths-h \
        ./src/main/Makefile \
+       ./src/main/radsniff.mk \
        ./src/main/checkrad.pl \
        ./src/main/radlast \
        ./src/main/radtest \
diff --git a/debian/freeradius.default b/debian/freeradius.default
new file mode 100644 (file)
index 0000000..1c31908
--- /dev/null
@@ -0,0 +1,3 @@
+# Options for the FreeRADIUS deamon.
+#FREERADIUS_OPTIONS="-d /etc/freeradius"
+
index 0738914..985c044 100755 (executable)
@@ -21,6 +21,10 @@ PROGRAM="/usr/sbin/freeradius"
 PIDFILE="/var/run/freeradius/freeradius.pid"
 DESCR="FreeRADIUS daemon"
 
+if [ -r /etc/default/$PROG ]; then
+  . /etc/default/$PROG
+fi
+
 test -f $PROGRAM || exit 0
 
 # /var/run may be a tmpfs
@@ -36,7 +40,7 @@ ret=0
 case "$1" in
         start)
                 log_daemon_msg "Starting $DESCR" "$PROG"
-                start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $PROGRAM || ret=$?
+                start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $PROGRAM -- $FREERADIUS_OPTIONS || ret=$?
                 log_end_msg $ret
                 exit $ret
                 ;;
index 022784c..a4cc755 100644 (file)
@@ -9,7 +9,7 @@ etc/freeradius/experimental.conf
 etc/freeradius/hints
 etc/freeradius/huntgroups
 etc/freeradius/ldap.attrmap
-etc/freeradius/modules/*
+etc/freeradius/mods-available/*
 etc/freeradius/policy.conf
 etc/freeradius/policy.txt
 etc/freeradius/preproxy_users
index fba93d7..27fe4f7 100644 (file)
@@ -23,7 +23,7 @@
 @@ -8,7 +8,7 @@
  SRCS        = rlm_sqlippool.c
  HEADERS     = $(top_builddir)/src/modules/rlm_sql/rlm_sql.h
- RLM_CFLAGS  = -I$(top_builddir)/src/modules/rlm_sql $(INCLTDL)
+ RLM_CFLAGS  = -I$(top_builddir)/src/modules/rlm_sql
 -RLM_LIBS    =
 +RLM_LIBS    += $(top_builddir)/src/modules/rlm_sql/.libs/rlm_sql.la
  RLM_INSTALL =
diff --git a/debian/patches/sql_modules.diff b/debian/patches/sql_modules.diff
new file mode 100644 (file)
index 0000000..8fd9ae6
--- /dev/null
@@ -0,0 +1,30 @@
+diff --git a/raddb/mods-available/sql b/raddb/mods-available/sql
+index 690c3a2..ec33ed1 100644
+--- a/raddb/mods-available/sql
++++ b/raddb/mods-available/sql
+@@ -103,5 +103,5 @@ sql {
+       nas_table = "nas"
+       # Read driver-specific configuration
+-      $INCLUDE sql/${database}/dialup.conf
++      #$INCLUDE sql/${database}/dialup.conf
+ }
+diff --git a/raddb/mods-available/sqlippool b/raddb/mods-available/sqlippool
+index 94fabc0..aa9ea6b 100644
+--- a/raddb/mods-available/sqlippool
++++ b/raddb/mods-available/sqlippool
+@@ -46,7 +46,7 @@ sqlippool {
+  #  same as the "database" field of the SQL module referred to in the
+  #  "sql-instance-name", above.
+  #
+-$INCLUDE sql/postgresql/ippool.conf
++#$INCLUDE sql/mysql/ippool.conf
+  
+  ## Logging configuration. (Comment out to disable logging)
+  sqlippool_log_exists = "Existing IP: %{reply:Framed-IP-Address} \
+@@ -63,5 +63,4 @@ $INCLUDE sql/postgresql/ippool.conf
+  sqlippool_log_nopool = "No Pool-Name defined \
+   (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})"
+-
+ }
index 6225382..f36632a 100644 (file)
@@ -15,7 +15,10 @@ FreeRADIUS 3.0.0 Mon 01 Jan 8:00:00 CEST 2010, urgency=medium
        * Moved eap.conf to modules/eap
        * Moved sql.conf to modules/sql
        * Preliminary support for Apple's Grand Central Dispatch.
+       * All modules have been moved to raddb/mods-available/
+         and raddb/modes-enabled/.  See raddb/README for more details.
        * Largely config-file compatible with 2.1.x.
+       * For upgrade instructions, see raddb/README
 
        Bug fixes
        * All known bug fixes are included.
diff --git a/main.mk b/main.mk
new file mode 100644 (file)
index 0000000..79d45ce
--- /dev/null
+++ b/main.mk
@@ -0,0 +1 @@
+SUBMAKEFILES := src/all.mk
index ed75468..c94fae8 100644 (file)
@@ -1,4 +1,4 @@
-.TH RADWHO 1 "7 April 2005" "" "FreeRADIUS Daemon"
+.TH RADWHO 1 "26 Dec 2011" "" "FreeRADIUS Daemon"
 .SH NAME
 radwho - show online users
 .SH SYNOPSIS
@@ -7,6 +7,8 @@ radwho - show online users
 .RB [ \-d
 .IR raddb_directory ]
 .RB [ \-f ]
+.RB [ \-F
+.IR radutmp_file ]
 .RB [ \-i ]
 .RB [ \-n ]
 .RB [ \-N
@@ -36,6 +38,9 @@ The directory that contains the RADIUS configuration files. Defaults to
 .IP \-f
 Behave as the 'fingerd' daemon - waits for one line of input, then
 prints the output with lines \\r\\n terminated.
+.IP \-F\ \fIradutmp_file\fP
+The file that contains the radutmp file.  If this is specified, -d is
+not necessary.
 .IP \-i
 Shows the session ID instead of the full name.
 .IP \-n
index 7e07c49..6e81ce2 100644 (file)
@@ -13,34 +13,53 @@ FILES = acct_users attrs attrs.access_reject attrs.accounting_response      \
        attrs.pre-proxy clients.conf dictionary templates.conf  \
        experimental.conf hints huntgroups ldap.attrmap                 \
        policy.txt preproxy_users proxy.conf radiusd.conf trigger.conf  \
-       users   policy.conf attrs.access_challenge
+       users policy.conf attrs.access_challenge README
+
+DEFAULT_SITES = default inner-tunnel
+
+DEFAULT_MODULES = acct_unique always attr_filter attr_rewrite chap checkval \
+               counter cui detail detail.log digest dynamic_clients eap \
+               echo exec expiration expr files inner-eap linelog logintime \
+               mschap ntlm_auth pap passwd preprocess radutmp realm \
+               replicate soh sradutmp unix utf8 wimax
 
 #
 #      This target is here for local debugging
 #
-all:
+all: sites-enabled mods-enabled
+
+.PHONY: sites-enabled
+sites-enabled:
        @if [ ! -d sites-enabled ]; then \
                mkdir sites-enabled; \
        fi
-       @if [ ! -f sites-enabled/default ]; then \
-               cd sites-enabled && ln -s ../sites-available/default; \
-       fi
-       @if [ ! -f sites-enabled/inner-tunnel ]; then \
-               cd sites-enabled && ln -s ../sites-available/inner-tunnel; \
-       fi
-ifneq "${OPENSSL_INCLUDE}" ""
-       @if [ ! -f sites-enabled/tls ]; then \
-               cd sites-enabled && ln -s ../sites-available/tls; \
+       @cd sites-enabled/; \
+        for x in $(DEFAULT_SITES); do \
+           if [ ! -f $$x ]; then \
+               ln -s ../sites-available/$$x; \
+           fi; \
+       done
+
+.PHONY: mods-enabled
+mods-enabled:
+       @if [ ! -d mods-enabled ]; then \
+               mkdir mods-enabled; \
        fi
-endif
+       @cd mods-enabled/; \
+        for x in $(DEFAULT_MODULES); do \
+           if [ ! -f $$x ]; then \
+               ln -s ../mods-available/$$x; \
+           fi; \
+       done
 
 install:
        $(INSTALL) -d -m 750    $(R)$(raddbdir)
        $(INSTALL) -d -m 750    $(R)$(raddbdir)/sites-available
        $(INSTALL) -d -m 750    $(R)$(raddbdir)/sites-enabled
-       $(INSTALL) -d -m 750    $(R)$(raddbdir)/modules
+       $(INSTALL) -d -m 750    $(R)$(raddbdir)/mods-available
+       $(INSTALL) -d -m 750    $(R)$(raddbdir)/mods-enabled
        @echo "Creating/updating files in $(R)$(raddbdir)"; \
-       for i in $(FILES) `find sites-available/ modules/ -type f -print | sed 's/.*CVS.*//;s/.*~//;s/.*#.*//' `; do \
+       for i in $(FILES) `find sites-available/ mods-available/ -type f -print | sed 's/.*~//;s/.*#.*//' `; do \
                [ ! -f $(R)$(raddbdir)/$$i ] && $(INSTALL) -m 640 $$i $(R)$(raddbdir)/$$i; \
                if [ "`find $$i -newer $(R)$(raddbdir)/$$i`" ]; then \
                        echo "** $(R)$(raddbdir)/$$i"; \
@@ -79,28 +98,22 @@ install:
                    fi; \
                  done; \
        fi
-       if [ ! -f $(R)$(raddbdir)/sites-enabled/default ]; then \
-               cd $(R)$(raddbdir)/sites-enabled/; \
-               ln -s ../sites-available/default; \
-       fi
-       if [ ! -f $(R)$(raddbdir)/sites-enabled/inner-tunnel ]; then \
-               cd $(R)$(raddbdir)/sites-enabled/; \
-               ln -s ../sites-available/inner-tunnel; \
-       fi
-       if [ ! -f $(R)$(raddbdir)/sites-enabled/control-socket ]; then \
-               cd $(R)$(raddbdir)/sites-enabled/; \
-               ln -s ../sites-available/control-socket; \
-       fi
-ifneq "${OPENSSL_INCLUDE}" ""
-       if [ ! -f $(R)$(raddbdir)/sites-enabled/control-socket ]; then \
-               cd $(R)$(raddbdir)/sites-enabled/; \
-               ln -s ../sites-available/control-socket; \
-       fi
-endif
+       @cd $(R)$(raddbdir)/sites-enabled/; \
+        for x in $(DEFAULT_SITES); do \
+           if [ ! -f $$x ]; then \
+               ln -s ../sites-available/$$x; \
+           fi; \
+       done
+       @cd $(R)$(raddbdir)/mods-enabled/; \
+        for x in $(DEFAULT_MODULES); do \
+           if [ ! -f $$x ]; then \
+               ln -s ../mods-available/$$x; \
+           fi; \
+       done
 
 clean:
-       @rm -rf sites-enabled/inner-tunnel sites-enabled/default \
-               sites-enabled/tls
+       @rm -rf *~ $(addprefix sites-enabled/,$(DEFAULT_SITES)) \
+               $(addprefix mods-enabled/,$(DEFAULT_MODULES))
 
 triggers:
        @grep exec_trigger `find ../src -name "*.c" -print` | grep '"' | sed -e 's/.*,//' -e 's/ *"//' -e 's/");.*//'
diff --git a/raddb/README b/raddb/README
new file mode 100644 (file)
index 0000000..b13033b
--- /dev/null
@@ -0,0 +1,98 @@
+Upgrading to Version 3.0
+========================
+
+The configuration for 3.0 is *largely* compatible with the 2.x
+configuration.  However, it is NOT possible to simply use the 2.x
+configuration as-is.  Instead, you should re-create it.
+
+Security
+--------
+
+A number of configuration items have moved into the "security"
+subsection of radiusd.conf.  If you use these, you should move them.
+Otherwise, they can be ignored.
+
+The list of moved options is:
+
+          chroot
+          user
+          group
+          allow_core_dumps
+          reject_delay
+          status_server
+
+
+Modules Directory
+-----------------
+
+  As of version 3.0, the "modules" directory no longer exists.
+
+  Instead, all "example" modules have been put into the
+"mods-available" directory.  Modules which can be loaded by the server
+are placed in the "mods-enabled" directory.
+
+  Modules can be enabled by creating a soft link.  For module "foo", do:
+
+    $ cd raddb
+    $ ln -s mods-available/foo mods-enabled/foo
+
+  To create "local" versions of the modules, we suggest copying the
+file instead.  This leaves the original file (with documentation) in
+the "mods-available" directory.  Local changes should go into the
+"mods-enabled" directory.
+
+
+SQL
+---
+
+  The SQL configuration has been moved from sql.conf to mods-available/sql.
+The sqlippool.conf file has also been moved.
+
+  The SQL module configuration has been changed.  The old connection
+pool options are no longer understood:
+
+       num_sql_socks
+       connect_failure_retry_delay
+       lifetime
+       max_queries
+
+  Instead, a connection pool configuration is used.  This
+configuration contains all of the functionality of the previous
+configuration, but in a more generic form.  It also is used in
+multiple modules, meaning that there are fewer different configuration
+items.  The mapping between the configuration items is:
+
+       num_sql_socks                   -> pool { max }
+       connect_failure_retry_delay     -> NOT SUPPORTED
+       lifetime                        -> pool { lifetime }
+       max_queries                     -> pool { uses }
+
+  The pool configuration adds a number of new configuration options,
+which allow the administrator to better control how FreeRADIUS uses
+SQL connection pools.
+
+
+EAP
+---
+
+  The EAP configuration has been moved from eap.conf to mods-available/eap.
+
+  It is otherwise unchanged.  You chould be able to copy your old
+eap.conf file directly to mods-enabled/eap.
+
+
+RadSec
+------
+
+  RadSec (or RADIUS over TLS) is now supported.  RADIUS over bare TCP
+is also supported, but is recommended only for secure networks.
+
+  See sites-available/tls for complete details on using TLS.  The
+server can both receive incoming TLS connections, and also originate
+outgoing TLS connections.
+
+  The TLS configuration is taken from the old EAP-TLS configuration.
+It is largely identical to the old EAP-TLS configuration, so it should
+be simple to use and configure.  It re-uses much of the EAP-TLS code,
+too.
+
index 7e84794..9e251f0 100644 (file)
@@ -18,7 +18,7 @@
 #  Ideally, the "configure" process should automatically enable this
 #  dictionary, but we don't yet do that.
 #
-#$INCLUDE      @prefix@/dictionary.dhcp
+#$INCLUDE      @prefix@/share/freeradius/dictionary.dhcp
 
 #
 #      The filename given here should be an absolute path. 
similarity index 100%
rename from raddb/modules/chap
rename to raddb/mods-available/chap
similarity index 100%
rename from raddb/modules/cui
rename to raddb/mods-available/cui
similarity index 93%
rename from raddb/modules/detail
rename to raddb/mods-available/detail
index 11005dc..2e68d06 100644 (file)
@@ -48,6 +48,13 @@ detail {
        #  people from seeing that information.
        detailperm = 0600
 
+       # The Unix group of the log file.
+       #
+       # The user that the server runs as must be in the specified
+       # system group otherwise this will fail to work.
+       #
+#      group = freerad
+
        #
        #  Every entry in the detail file has a header which
        #  is a timestamp.  By default, we use the ctime
diff --git a/raddb/mods-available/dhcp_sqlippool b/raddb/mods-available/dhcp_sqlippool
new file mode 100644 (file)
index 0000000..39358b2
--- /dev/null
@@ -0,0 +1,30 @@
+##  Configuration for DHCP to use SQL IP Pools.
+##
+##  See sqlippool.conf for common configuration explanation
+##
+##  $Id$
+
+sqlippool dhcp_sqlippool {
+       sql-instance-name = "sql"
+
+       ippool_table = "radippool"
+
+       lease-duration = 7200
+
+       # Client's MAC address is mapped to Calling-Station-Id in policy.conf
+       pool-key = "%{Calling-Station-Id}"
+
+       # For now, it only works with MySQL.
+       $INCLUDE ${confdir}/sql/mysql/ippool-dhcp.conf
+       sqlippool_log_exists = "DHCP: Existing IP: %{reply:Framed-IP-Address} (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})"
+
+       sqlippool_log_success = "DHCP: Allocated IP: %{reply:Framed-IP-Address} from %{control:Pool-Name} (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})"
+
+       sqlippool_log_clear = "DHCP: Released IP %{Framed-IP-Address} (did %{Called-Station-Id} cli %{Calling-Station-Id} user %{User-Name})"
+
+       sqlippool_log_failed = "DHCP: IP Allocation FAILED from %{control:Pool-Name} (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})"
+
+       sqlippool_log_nopool = "DHCP: No Pool-Name defined (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})"
+
+}
similarity index 90%
rename from raddb/modules/eap
rename to raddb/mods-available/eap
index 26885e4..26a7f43 100644 (file)
                        CA_file = ${cadir}/ca.pem
 
                        #
+                       #  If OpenSSL supports TLS-PSK, then we can use
+                       #  a PSK identity and (hex) password.  When the
+                       #  following two configuration items are specified,
+                       #  then certificate-based configuration items are
+                       #  not allowed.  e.g.:
+                       #
+                       #       private_key_password
+                       #       private_key_file
+                       #       certificate_file
+                       #       CA_file
+                       #       CA_path
+                       #
+                       #  For now, the identity is fixed, and must be the
+                       #  same on the client.  The passphrase must be a hex
+                       #  value, and can be up to 256 hex digits.
+                       #
+                       #  Future versions of the server may be able to
+                       #  look up the shared key (hexphrase) based on the
+                       #  identity.
+                       #
+               #       psk_identity = "test"
+               #       psk_hexphrase = "036363823"
+
+                       #
                        #  For DH cipher suites to work, you have to
                        #  run OpenSSL to create the DH file first:
                        #
                              #  Responder is running as a vhost.
                              #
                              url = "http://127.0.0.1/ocsp/"
+
+                             #
+                             # If the OCSP Responder can not cope with nonce
+                             # in the request, then it can be disabled here.
+                             #
+                             # For security reasons, disabling this option
+                             # is not recommended as nonce protects against
+                             # replay attacks.
+                             #
+                             # Note that Microsoft AD Certificate Services OCSP
+                             # Responder does not enable nonce by default. It is
+                             # more secure to enable nonce on the responder than
+                             # to disable it in the query here.
+                             # See http://technet.microsoft.com/en-us/library/cc770413%28WS.10%29.aspx
+                             #
+                             # use_nonce = yes
+
+                             #
+                             # Number of seconds before giving up waiting
+                             # for OCSP response. 0 uses system default.
+                             #
+                             # timeout = 0
+
+                             #
+                             # Normally an error in querying the OCSP
+                             # responder (no response from server, server did
+                             # not understand the request, etc) will result in
+                             # a validation failure.
+                             #
+                             # To treat these errors as 'soft' failures and
+                             # still accept the certificate, enable this
+                             # option.
+                             # 
+                             # Warning: this may enable clients with revoked
+                             # certificates to connect if the OCSP responder
+                             # is not available. Use with caution.
+                             #
+                             # softfail = no
                        }
                }
 
similarity index 100%
rename from raddb/modules/echo
rename to raddb/mods-available/echo
similarity index 100%
rename from raddb/modules/exec
rename to raddb/mods-available/exec
similarity index 100%
rename from raddb/modules/expr
rename to raddb/mods-available/expr
similarity index 100%
rename from raddb/modules/krb5
rename to raddb/mods-available/krb5
similarity index 100%
rename from raddb/modules/ldap
rename to raddb/mods-available/ldap
similarity index 93%
rename from raddb/modules/linelog
rename to raddb/mods-available/linelog
index 2be4d81..10f4697 100644 (file)
@@ -26,6 +26,14 @@ linelog {
        permissions = 0600
 
        #
+       # The Unix group of the log file.
+       #
+       # The user that freeradius runs as must be in the specified
+       # group, otherwise it will not be possible to set the group.
+       #
+       # group = freerad
+
+       #
        #  The default format string.
        format = "This is a log message for %{User-Name}"
 
similarity index 100%
rename from raddb/modules/otp
rename to raddb/mods-available/otp
similarity index 100%
rename from raddb/modules/pam
rename to raddb/mods-available/pam
similarity index 100%
rename from raddb/modules/pap
rename to raddb/mods-available/pap
similarity index 80%
rename from raddb/modules/passwd
rename to raddb/mods-available/passwd
index b7ac2a9..92496bf 100644 (file)
 #            Attributes marked as '=' are added to reply_items instead
 #            of default configure_itmes
 #
-#           Attributse marked as '~' are added to request_items
+#           Attributes marked as '~' are added to request_items
 #
 #            Field marked as ',' may contain a comma separated list
 #            of attributes.
 #
-#   hashsize - hashtable size. If 0 or not specified records are not
-#            stored in memory and file is read on every request.
-#           This configuration is *not* recommended, as it can be
-#           very slow.  The "passwd" module reloads its configuration
-#           on HUP, so setting "hashsize = 0" is unnecessary.
+#   hashsize - hashtable size.  Setting it to 0 is no longer permitted
+#              A future version of the server will have the module
+#              automatically determine the hash size.  Having it set
+#              manually should not be necessary.
 #
 #   allowmultiplekeys - if many records for a key are allowed
 #
similarity index 100%
rename from raddb/modules/perl
rename to raddb/mods-available/perl
similarity index 100%
rename from raddb/modules/soh
rename to raddb/mods-available/soh
similarity index 80%
rename from raddb/modules/sql
rename to raddb/mods-available/sql
index 8f16ab1..a0f7d6a 100644 (file)
@@ -81,6 +81,9 @@ sql {
        #  lifetime
        #  max_queries
 
+       #  The connection pool is new for 3.0, and will be used in many
+       #  modules, for all kinds of connection-related activity.
+       #
        pool {
                # Number of connections to start
                start = 5
@@ -89,9 +92,15 @@ sql {
                min = 4
 
                # Maximum number of connections
+               #
+               # If these connections are all in use and a new one
+               # is requested, the request will NOT get a connection.
                max = 10
 
                # Spare connections to be left idle
+               #
+               # NOTE: Idle connections WILL be closed if "idle_timeout"
+               # is set.
                spare = 3
 
                # Number of uses before the connection is closed
@@ -105,6 +114,16 @@ sql {
                # idle timeout (in seconds).  A connection which is
                # unused for this length of time will be closed.
                idle_timeout = 60
+
+               # NOTE: All configuration settings are enforced.  If a
+               # connection is closed because of "idle_timeout",
+               # "uses", or "lifetime", then the total number of
+               # connections MAY fall below "min".  When that
+               # happens, it will open a new connection.  It will
+               # also log a WARNING message.
+               #
+               # The solution is to either lower the "min" connections,
+               # or increase lifetime/idle_timeout.
        }
 
        # Set to 'yes' to read radius clients from the database ('nas' table)
similarity index 100%
rename from raddb/modules/unix
rename to raddb/mods-available/unix
similarity index 100%
rename from raddb/modules/utf8
rename to raddb/mods-available/utf8
index 3955429..520cad5 100644 (file)
@@ -333,4 +333,29 @@ policy {
                        noop
                }
        }
+
+       #  Assign compatibility data to request for sqlippool
+       dhcp_sqlippool.post-auth {
+
+
+               #  Do some minor hacks to the request so that it looks
+               #  like a RADIUS request to the SQL IP Pool module.
+               update request {
+                       User-Name = "DHCP-%{DHCP-Client-Hardware-Address}"
+                       Calling-Station-Id = "%{DHCP-Client-Hardware-Address}"
+                       NAS-IP-Address = "%{%{DHCP-Gateway-IP-Address}:-127.0.0.1}"
+                       Acct-Status-Type = Start
+               }
+
+               #  Call the actual module
+               dhcp_sqlippool
+
+               #  Convert Framed-IP-Address to DHCP, but only if we
+               #  actually allocated an address.
+               if (ok) {
+                       update reply {
+                               DHCP-Your-IP-Address = "%{reply:Framed-IP-Address}"
+                       }
+               }
+       }
 }
index edb50c9..be2d2f6 100644 (file)
@@ -680,13 +680,13 @@ modules {
        #
 
        #
-       #  As of 2.0.5, most of the module configurations are in a
-       #  sub-directory.  Files matching the regex /[a-zA-Z0-9_.]+/
-       #  are loaded.  The modules are initialized ONLY if they are
-       #  referenced in a processing section, such as authorize,
-       #  authenticate, accounting, pre/post-proxy, etc.
+       #  As of 3.0, modules are in mods-enabled/.  Files matching
+       #  the regex /[a-zA-Z0-9_.]+/ are loaded.  The modules are
+       #  initialized ONLY if they are referenced in a processing
+       #  section, such as authorize, authenticate, accounting,
+       #  pre/post-proxy, etc.
        #
-       $INCLUDE ${confdir}/modules/
+       $INCLUDE ${confdir}/mods-enabled/
 }
 
 # Instantiation
diff --git a/raddb/sites-available/chbind b/raddb/sites-available/chbind
new file mode 100644 (file)
index 0000000..4b07bd3
--- /dev/null
@@ -0,0 +1,19 @@
+server chbind{
+    authorize {
+       if (GSS-Acceptor-Service-Name && outer.request:GSS-Acceptor-Service-Name != GSS-Acceptor-Service-Name ) {
+           reject
+       }
+       update reply {
+           GSS-Acceptor-Service-NAME == "%{GSS-ACCEPTOR-SERVICE-Name}"
+           GSS-ACCEPTOR-Host-Name == "%{GSS-Acceptor-Host-Name}"
+           GSS-Acceptor-Realm-Name == "%{GSS-Acceptor-Realm-Name}"
+       }
+       if (GSS-Acceptor-Service-Name || GSS-Acceptor-Realm-Name || GSS-Acceptor-Host-Name) {
+           update control {
+               Chbind-Response-Code := success
+           }
+       }
+       handled
+    }
+}
+
index 2639900..6f207ad 100644 (file)
@@ -148,6 +148,9 @@ dhcp DHCP-Discover {
        # ...
        #}
 
+       #  Or, allocate IPs from the DHCP pool in SQL.
+#      dhcp_sqlippool
+
        ok
 }
 
@@ -180,6 +183,9 @@ dhcp DHCP-Request {
        # ...
        #}
 
+       #  Or, allocate IPs from the DHCP pool in SQL.
+#      dhcp_sqlippool
+
        ok
 }
 
diff --git a/raddb/sql/mysql/ippool-dhcp.conf b/raddb/sql/mysql/ippool-dhcp.conf
new file mode 100644 (file)
index 0000000..1716ba9
--- /dev/null
@@ -0,0 +1,75 @@
+# -*- text -*-
+##
+## ippool-dhcp.conf -- MySQL queries for sqlippool-dhcp instance
+## Only post-auth method is used
+##
+##     $Id$
+
+## This series of queries allocates an IP address
+## First, clear expired entries
+ allocate-clear = "UPDATE ${ippool_table} \
+  SET nasipaddress = '', pool_key = 0, \
+  callingstationid = '', username = '', \
+  expiry_time = NULL \
+  WHERE expiry_time <= NOW() - INTERVAL 1 SECOND \
+  "
+
+## Then find an available IP address
+## The ORDER BY clause of this query tries to allocate the same IP address
+## which user had last session regardless of expiry time 
+## to handle DHCP request and duplicates from the same client
+allocate-find = "SELECT framedipaddress FROM ${ippool_table} \
+ WHERE pool_name = '%{control:Pool-Name}' AND \
+ ( \
+ (callingstationid = '%{Calling-Station-Id}') OR \
+ (expiry_time < NOW() OR expiry_time IS NULL) \
+ ) \
+ ORDER BY (callingstationid = '%{Calling-Station-Id}') DESC, \
+ expiry_time DESC\
+ LIMIT 1 \
+ FOR UPDATE"
+
+## If an IP could not be allocated, check to see if the pool exists or not
+## This allows the module to differentiate between a full pool and no pool
+## Note: If you are not running redundant pool modules this query may be
+## commented out to save running this query every time an ip is not allocated.
+pool-check = "SELECT id FROM ${ippool_table} \
+ WHERE pool_name='%{control:Pool-Name}' LIMIT 1"
+
+
+## This is the final IP Allocation query, which saves the allocated ip details
+allocate-update = "UPDATE ${ippool_table} \
+ SET nasipaddress = '%{NAS-IP-Address}', pool_key = '${pool-key}', \
+ callingstationid = '%{Calling-Station-Id}', username = '%{User-Name}', \
+ calledstationid = 'Freeradius-DHCP', \
+ expiry_time = GREATEST( \
+  IF(ISNULL(expiry_time),'0000-00-00 00:00:00',expiry_time), \
+  NOW() + INTERVAL ${lease-duration} SECOND) \
+ WHERE framedipaddress = '%I' AND \
+ ( \
+ (callingstationid = '%{Calling-Station-Id}') OR \
+ (expiry_time < NOW() OR expiry_time IS NULL) \
+ ) \
+ "
+
+## This series of queries frees an IP number when an accounting
+## START record arrives. Unused, but must be set to non-empty query
+start-update = "SELECT NOW()"
+
+## This series of queries frees an IP number when an accounting
+## STOP record arrives. Unused, but must be set to non-empty query
+stop-clear = "SELECT NOW()"
+
+## This series of queries frees an IP number when an accounting
+## ALIVE record arrives. Unused, but must be set to non-empty query
+alive-update = "SELECT NOW()"
+
+## This series of queries frees the IP numbers allocate to a
+## NAS when an accounting ON record arrives. Unused, but must be set
+## to non-empty query
+on-clear = "SELECT NOW()"
+
+## This series of queries frees the IP numbers allocate to a
+## NAS when an accounting OFF record arrives. Unused, but must be set
+## to non-empty query
+off-clear = "SELECT NOW()"
index 29d1524..f3954e9 100644 (file)
@@ -289,11 +289,9 @@ fi
 %attr(640,root,radiusd) %config(noreplace) /etc/raddb/clients.conf
 %config(noreplace) /etc/raddb/hints
 %config(noreplace) /etc/raddb/huntgroups
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/sqlippool.conf
 %attr(640,root,radiusd) %config(noreplace) /etc/raddb/preproxy_users
 %attr(640,root,radiusd) %config(noreplace) /etc/raddb/proxy.conf
 %attr(640,root,radiusd) %config(noreplace) /etc/raddb/radiusd.conf
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/sql.conf
 %dir %attr(750,root,radiusd) /etc/raddb/sql
 #%attr(640,root,radiusd) %config(noreplace) /etc/raddb/sql/oracle/*
 %attr(640,root,radiusd) %config(noreplace) /etc/raddb/users
@@ -307,60 +305,16 @@ fi
 %attr(640,root,radiusd) %config(noreplace) /etc/raddb/sites-available/*
 %dir %attr(750,root,radiusd) /etc/raddb/sites-enabled
 %attr(640,root,radiusd) %config(noreplace) /etc/raddb/sites-enabled/*
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/eap.conf
 %config(noreplace) %attr(640,root,radiusd) /etc/raddb/example.pl
 %attr(640,root,radiusd) %config(noreplace) /etc/raddb/policy.conf
 %config(noreplace) /etc/raddb/policy.txt
 %attr(640,root,radiusd) %config(noreplace) /etc/raddb/templates.conf
 %dir %attr(750,root,radiusd) /etc/raddb/modules
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/acct_unique
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/always
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/attr_filter
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/attr_rewrite
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/chap
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/checkval
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/counter
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/cui
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/detail
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/detail.example.com
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/detail.log
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/digest
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/dynamic_clients
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/echo
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/etc_group
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/exec
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/expiration
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/expr
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/files
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/inner-eap
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/ippool
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/logintime
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/linelog
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/mac2ip
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/mac2vlan
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/mschap
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/ntlm_auth
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/opendirectory
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/otp
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/pam
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/pap
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/perl
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/passwd
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/policy
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/preprocess
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/radutmp
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/realm
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/redis
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/rediswho
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/replicate
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/smbpasswd
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/smsotp
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/soh
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/sql_log
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/sqlcounter_expire_on_login
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/sradutmp
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/unix
-%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/wimax
+%dir %attr(750,root,radiusd) /etc/raddb/mods-available
+%attr(640,root,radiusd) %config(noreplace) /etc/raddb/mods-available/*
+%dir %attr(750,root,radiusd) /etc/raddb/mods-enabled
+%attr(640,root,radiusd) %config(noreplace) /etc/raddb/mods-enabled/*
+%attr(640,root,radiusd) %config(noreplace) /etc/raddb/modules/*
 %dir %attr(755,radiusd,radiusd) /var/run/radiusd/
 # binaries
 %defattr(-,root,root)
diff --git a/scripts/boiler.mk b/scripts/boiler.mk
new file mode 100644 (file)
index 0000000..521a975
--- /dev/null
@@ -0,0 +1,566 @@
+# boilermake: A reusable, but flexible, boilerplate Makefile.
+#
+# Copyright 2008, 2009, 2010 Dan Moulding, Alan T. DeKok
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Caution: Don't edit this Makefile! Create your own main.mk and other
+#          submakefiles, which will be included by this Makefile.
+#          Only edit this if you need to modify boilermake's behavior (fix
+#          bugs, add features, etc).
+
+# Note: Parameterized "functions" in this makefile that are marked with
+#       "USE WITH EVAL" are only useful in conjuction with eval. This is
+#       because those functions result in a block of Makefile syntax that must
+#       be evaluated after expansion. Since they must be used with eval, most
+#       instances of "$" within them need to be escaped with a second "$" to
+#       accomodate the double expansion that occurs when eval is invoked.
+
+# ADD_CLEAN_RULE - Parameterized "function" that adds a new rule and phony
+#   target for cleaning the specified target (removing its build-generated
+#   files).
+#
+#   USE WITH EVAL
+#
+define ADD_CLEAN_RULE
+    clean: clean_$(notdir ${1})
+    .PHONY: clean_$(notdir ${1})
+    clean_$(notdir ${1}):
+       @$(strip rm -f ${${1}_BUILD}/${1} ${${1}_NOLIBTOOL} ${${1}_BUILD}/${${1}_RELINK} $${${1}_OBJS} $${${1}_DEPS} $${${1}_OBJS:%.${OBJ_EXT}=%.[do]}) $(if ${TARGET_DIR},$${TARGET_DIR}/$(notdir ${1}))
+       $${${1}_POSTCLEAN}
+
+endef
+
+# FILTER_DEPENDS: function to turn a *.d file into a *.mk file.
+#   We start off with the dependencies as created by the compiler,
+#   CPP, or makedepend.  We then ensure that there is an empty dependency
+#   for each header file.  The blank target ensures that the build
+#   can proceed even if the header file has been deleted.
+#
+#  COMMON filters:
+#      remove comments
+#      remove dependencies on global include files
+#      remove empty dependencies
+#      remove CPP hacks like "foo: <built-in>"
+#
+#  1) Filter the .d file to remove unnecessary cruft
+#
+#      COMMON
+#      Replace ".o" with "${OBJ_EXT}"
+#      delete empty continuation lines
+#      delete blank lines
+#      replace "build/" with "${BUILD_DIR}/" when it's at the start of a line
+#      delete references to ${BUILD_DIR}/make/include, the "config.mk"
+#      file adds these dependencies automatically.
+#      replace "build/" with "${BUILD_DIR}/" when it's in the middle of a line
+#      
+#      remove sequential duplicate lines
+#      
+#  2) Create empty dependencies from the files
+#
+#      COMMON
+#      remove existing targets
+#      remove continuations (to make the targets stand by themselves)
+#      delete blank lines
+#      add in empty dependency for each file.
+#      remove sequential duplicate lines
+#
+define FILTER_DEPENDS
+       @mkdir -p $$(dir $${BUILD_DIR}/make/src/$$*)
+       @mkdir -p $$(dir $${BUILD_DIR}/objs/$$*)
+       @sed  -e 's/#.*//' \
+         -e 's,^$${top_srcdir},$$$${top_srcdir},' \
+         -e 's, $${top_srcdir}, $$$${top_srcdir},' \
+         -e 's,^$${BUILD_DIR},$$$${BUILD_DIR},' \
+         -e 's, $${BUILD_DIR}/make/include/[^ :]*,,' \
+         -e 's, $${BUILD_DIR}, $$$${BUILD_DIR},' \
+         -e 's, /[^: ]*,,g' \
+         -e 's,^ *[^:]* *: *$$$$,,' \
+         -e '/: </ d' \
+         -e 's/\.o: /.$$$${OBJ_EXT}: /' \
+         -e '/^ *\\$$$$/ d' \
+         < $${BUILD_DIR}/objs/$$*.d | sed -e '$$$$!N; /^\(.*\)\n\1$$$$/!P; D' \
+         >  $${BUILD_DIR}/make/src/$$*.mk
+       @sed -e 's/#.*//' \
+         -e 's, $${BUILD_DIR}/make/include/[^ :]*,,' \
+         -e 's, /[^: ]*,,g' \
+         -e 's,^ *[^:]* *: *$$$$,,' \
+         -e '/: </ d' \
+         -e 's/^[^:]*: *//' \
+         -e 's/ *\\$$$$//' \
+         -e 's/$$$$/ :/' \
+         < $${BUILD_DIR}/objs/$$*.d | sed -e '$$$$!N; /^\(.*\)\n\1$$$$/!P; D' \
+        >> $${BUILD_DIR}/make/src/$$*.mk
+        @rm -f $${BUILD_DIR}/objs/$$*.d
+endef
+
+# ADD_OBJECT_RULE - Parameterized "function" that adds a pattern rule, using
+#   the commands from the second argument, for building object files from
+#   source files with the filename extension specified in the first argument.
+#
+#   This function assumes that the C/C++ sources files have filenames
+#   *relative* to the source root.  If they have absolute pathnames, it
+#   creates the wrong filenames...
+#
+#   USE WITH EVAL
+#
+ifeq "${CPP_MAKEDEPEND}" "yes"
+define ADD_OBJECT_RULE
+$${BUILD_DIR}/objs/%.${OBJ_EXT} $${BUILD_DIR}/objs/%.d: ${1}
+       ${2}
+       $${CPP} $${CPPFLAGS} $${SRC_INCDIRS} $${SRC_DEFS} $$< | sed \
+         -n 's,^\# *[0-9][0-9]* *"\([^"]*\)".*,$$@: \1,p' > $${BUILD_DIR}/objs/$$*.d
+${FILTER_DEPENDS}
+endef
+
+else
+define ADD_OBJECT_RULE
+$${BUILD_DIR}/objs/%.${OBJ_EXT} $${BUILD_DIR}/objs/%.d: ${1}
+       ${2}
+${FILTER_DEPENDS}
+endef
+endif
+
+# ADD_TARGET_DIR - Parameterized "function" that makes a link from
+#   TARGET_DIR to the executable or library in the BUILD_DIR directory.
+#
+#   USE WITH EVAL
+#
+ifneq "${TARGET_DIR}" ""
+    define ADD_TARGET_DIR
+        all: $${TARGET_DIR}/$$(notdir ${1})
+
+        $${TARGET_DIR}/$$(notdir ${1}): ${1}
+           [ -f $${TARGET_DIR}/$$(notdir ${1}) ] || ln -s ${1} $${TARGET_DIR}/$$(notdir ${1})
+
+    endef
+endif
+
+# ADD_TARGET_TO_ALL - Parameterized "function" that adds the target,
+#   and makes "all" depend on it.
+#
+#   USE WITH EVAL
+#
+define ADD_TARGET_TO_ALL
+    all: ${1}
+
+endef
+
+# ADD_TARGET_RULE.* - Parameterized "functions" that adds a new target to the
+#   Makefile.  There should be one ADD_TARGET_RULE definition for each
+#   type of target that is used in the build.  
+#
+#   New rules can be added by copying one of the existing ones, and
+#   replacing the line after the "mkdir"
+#
+
+# ADD_TARGET_RULE.exe - Build an executable target.
+#
+#   USE WITH EVAL
+#
+define ADD_TARGET_RULE.exe
+    # So "make ${1}" works
+    .PHONY: ${1}
+    ${1}: $${${1}_BUILD}/${1}
+
+    # Create executable ${1}
+    $${${1}_BUILD}/${1}: $${${1}_OBJS} $${${1}_PRBIN} $${${1}_PRLIBS}
+           @$(strip mkdir -p $(dir $${${1}_BUILD}/${1}))
+           @$(ECHO) LINK $${${1}_BUILD}/${1}
+           @$${${1}_LINKER} -o $${${1}_BUILD}/${1} $${RPATH_FLAGS} $${LDFLAGS} \
+                $${${1}_LDFLAGS} $${${1}_OBJS} $${${1}_PRLIBS} \
+                $${LDLIBS} $${${1}_LDLIBS}
+           @$${${1}_POSTMAKE}
+
+endef
+
+# ADD_TARGET_RULE.a - Build a static library target.
+#
+#   USE WITH EVAL
+#
+define ADD_TARGET_RULE.a
+    # So "make ${1}" works
+    .PHONY: ${1}
+    ${1}: $${${1}_BUILD}/${1}
+
+    # Create static library ${1}
+    $${${1}_BUILD}/${1}: $${${1}_OBJS} $${${1}_PREREQS}
+           @$(strip mkdir -p $(dir $${${1}_BUILD}/${1}))
+           @$(ECHO) LINK $${${1}_BUILD}/${1}
+           @$${AR} $${ARFLAGS} $${${1}_BUILD}/${1} $${${1}_OBJS}
+           @$${${1}_POSTMAKE}
+
+endef
+
+# ADD_TARGET_RULE.so - Build a ".so" target.
+#
+#   USE WITH EVAL
+#
+define ADD_TARGET_RULE.so
+$(error Please add rules to build a ".so" file.)
+endef
+
+# ADD_TARGET_RULE.dll - Build a ".dll" target.
+#
+#   USE WITH EVAL
+#
+define ADD_TARGET_RULE.dll
+$(error Please add rules to build a ".dll" file.)
+endef
+
+# ADD_TARGET_RULE.dylib - Build a ".dylib" target.
+#
+#   USE WITH EVAL
+#
+define ADD_TARGET_RULE.dylib
+$(error Please add rules to build a ".dylib" file.)
+endef
+
+# CANONICAL_PATH - Given one or more paths, converts the paths to the canonical
+#   form. The canonical form is the path, relative to the project's top-level
+#   directory (the directory from which "make" is run), and without
+#   any "./" or "../" sequences. For paths that are not  located below the
+#   top-level directory, the canonical form is the absolute path (i.e. from
+#   the root of the filesystem) also without "./" or "../" sequences.
+define CANONICAL_PATH
+$(patsubst ${CURDIR}/%,%,$(abspath ${1}))
+endef
+
+# COMPILE_C_CMDS - Commands for compiling C source code.
+define COMPILE_C_CMDS
+       @mkdir -p $(dir $@)
+       @$(ECHO) CC $<
+       @$(strip ${COMPILE.c} -o $@ -c -MD ${CFLAGS} ${SRC_CFLAGS} ${INCDIRS} \
+           ${SRC_INCDIRS} ${SRC_DEFS} ${DEFS} $<)
+endef
+
+# COMPILE_CXX_CMDS - Commands for compiling C++ source code.
+define COMPILE_CXX_CMDS
+       @mkdir -p $(dir $@)
+       @$(strip ${COMPILE.cxx} -o $@ -c -MD ${CXXFLAGS} ${SRC_CXXFLAGS} ${INCDIRS} \
+           ${SRC_INCDIRS} ${SRC_DEFS} ${DEFS} $<)
+endef
+
+# INCLUDE_SUBMAKEFILE - Parameterized "function" that includes a new
+#   "submakefile" fragment into the overall Makefile. It also recursively
+#   includes all submakefiles of the specified submakefile fragment.
+#
+#   USE WITH EVAL
+#
+define INCLUDE_SUBMAKEFILE
+    # Initialize all variables that can be defined by a makefile fragment, then
+    # include the specified makefile fragment.
+    TARGET :=
+    TGT_LDFLAGS :=
+    TGT_LDLIBS :=
+    TGT_LINKER :=
+    TGT_POSTCLEAN :=
+    TGT_POSTMAKE :=
+    TGT_PREREQS :=
+    TGT_POSTINSTALL :=
+    TGT_INSTALLDIR := ..
+    TGT_CHECK_HEADERS :=
+    TGT_CHECK_LIBS :=
+
+    SOURCES :=
+    SRC_CFLAGS :=
+    SRC_CXXFLAGS :=
+    SRC_DEFS :=
+    SRC_INCDIRS :=
+    MAN :=
+
+    SUBMAKEFILES :=
+
+    # A directory stack is maintained so that the correct paths are used as we
+    # recursively include all submakefiles. Get the makefile's directory and
+    # push it onto the stack.
+    DIR := $(call CANONICAL_PATH,$(dir ${1}))
+    DIR_STACK := $$(call PUSH,$${DIR_STACK},$${DIR})
+
+    include ${1}
+
+    # Initialize internal local variables.
+    OBJS :=
+
+    # Determine which target this makefile's variables apply to. A stack is
+    # used to keep track of which target is the "current" target as we
+    # recursively include other submakefiles.
+    ifneq "$$(strip $${TARGET})" ""
+        # This makefile defined a new target. Target variables defined by this
+        # makefile apply to this new target. Initialize the target's variables.
+
+        # libs go into ${BUILD_DIR}/lib
+        # everything else goes into ${BUILD_DIR}/bin
+#        TGT := $$(strip $$(if $$(suffix $${TARGET}),$${BUILD_DIR}/lib,$${BUILD_DIR}/bin)/$${TARGET})
+        TGT := $${TARGET}
+
+        # A "hook" to rewrite "libfoo.a" -> "libfoo.la" when using libtool
+        $$(eval $$(call ADD_LIBTOOL_SUFFIX))
+
+        ALL_TGTS += $${TGT}
+        $${TGT}_LDFLAGS := $${TGT_LDFLAGS}
+        $${TGT}_LDLIBS := $${TGT_LDLIBS}
+        $${TGT}_LINKER := $${TGT_LINKER}
+        $${TGT}_POSTMAKE := $${TGT_POSTMAKE}
+        $${TGT}_POSTCLEAN := $${TGT_POSTCLEAN}
+        $${TGT}_POSTINSTALL := $${TGT_POSTINSTALL}
+        $${TGT}_PREREQS := $${TGT_PREREQS}
+        $${TGT}_PRBIN := $$(addprefix $${BUILD_DIR}/bin/,$$(filter-out %.a %.so %.la,$${TGT_PREREQS}))
+        $${TGT}_PRLIBS := $$(addprefix $${BUILD_DIR}/lib/,$$(filter %.a %.so %.la,$${TGT_PREREQS}))
+        $${TGT}_DEPS :=
+        $${TGT}_OBJS :=
+        $${TGT}_SOURCES :=
+        $${TGT}_MAN := $${MAN}
+        $${TGT}_SUFFIX := $$(if $$(suffix $${TGT}),$$(suffix $${TGT}),.exe)
+        $${TGT}_BUILD := $$(if $$(suffix $${TGT}),$${BUILD_DIR}/lib,$${BUILD_DIR}/bin)
+        $${TGT}_MAKEFILES += ${1}
+        $${TGT}_CHECK_HEADERS := $${TGT_CHECK_HEADERS}
+        $${TGT}_CHECK_LIBS := $${TGT_CHECK_LIBS}
+    else
+        # The values defined by this makefile apply to the the "current" target
+        # as determined by which target is at the top of the stack.
+        TGT := $$(strip $$(call PEEK,$${TGT_STACK}))
+        $${TGT}_LDFLAGS   += $${TGT_LDFLAGS}
+        $${TGT}_LDLIBS    += $${TGT_LDLIBS}
+        $${TGT}_POSTCLEAN += $${TGT_POSTCLEAN}
+        $${TGT}_POSTMAKE  += $${TGT_POSTMAKE}
+        $${TGT}_PREREQS   += $${TGT_PREREQS}
+    endif
+
+    # Push the current target onto the target stack.
+    TGT_STACK := $$(call PUSH,$${TGT_STACK},$${TGT})
+
+    ifneq "$$(strip $${SOURCES})" ""
+        # This makefile builds one or more objects from source. Validate the
+        # specified sources against the supported source file types.
+        BAD_SRCS := $$(strip $$(filter-out $${ALL_SRC_EXTS},$${SOURCES}))
+        ifneq "$${BAD_SRCS}" ""
+            $$(error Unsupported source file(s) found in ${1} [$${BAD_SRCS}])
+        endif
+
+        # Qualify and canonicalize paths.
+        SOURCES     := $$(call QUALIFY_PATH,$${DIR},$${SOURCES})
+        SOURCES     := $$(call CANONICAL_PATH,$${SOURCES})
+        SRC_INCDIRS := $$(call QUALIFY_PATH,$${DIR},$${SRC_INCDIRS})
+        SRC_INCDIRS := $$(call CANONICAL_PATH,$${SRC_INCDIRS})
+
+        # Save the list of source files for this target.
+        $${TGT}_SOURCES += $${SOURCES}
+
+        # Convert the source file names to their corresponding object file
+        # names.
+        OBJS := $$(addprefix $${BUILD_DIR}/objs/,\
+                   $$(addsuffix .${OBJ_EXT},$$(basename $${SOURCES})))
+
+        # Add the objects to the current target's list of objects, and create
+        # target-specific variables for the objects based on any source
+        # variables that were defined.
+        $${TGT}_OBJS += $${OBJS}
+        $${TGT}_DEPS += $$(addprefix $${BUILD_DIR}/make/src/,\
+                   $$(addsuffix .mk,$$(basename $${SOURCES})))
+
+        # A "hook" to define variables needed by the "legacy" makefiles.
+        $$(eval $$(call ADD_LEGACY_VARIABLES,$$(dir ${1}),$${TGT}))
+
+        $${OBJS}: SRC_CFLAGS := $${SRC_CFLAGS}
+        $${OBJS}: SRC_CXXFLAGS := $${SRC_CXXFLAGS}
+        $${OBJS}: SRC_DEFS := $$(addprefix -D,$${SRC_DEFS})
+        $${OBJS}: SRC_INCDIRS := $$(addprefix -I,$${SRC_INCDIRS})
+    endif
+
+    ifneq "$$(strip $${SUBMAKEFILES})" ""
+        # This makefile has submakefiles. Recursively include them.
+        $$(foreach MK,$${SUBMAKEFILES},\
+           $$(eval $$(call INCLUDE_SUBMAKEFILE,\
+                      $$(call CANONICAL_PATH,\
+                         $$(call QUALIFY_PATH,$${DIR},$${MK})))))
+    endif
+
+    # Reset the "current" target to it's previous value.
+    TGT_STACK := $$(call POP,$${TGT_STACK})
+    # If we're about to change targets, create the rules for the target
+    ifneq "$${TGT}" "$$(call PEEK,$${TGT_STACK})"
+        # add rules to build the target, and have "all" depend on it.
+        $$(eval $$(call ADD_TARGET_TO_ALL,$${TGT}))
+
+        # A "hook" to add rules for ${TARGET_DIR}/foo, if TARGET_DIR
+        # is defined.  Otherwise, we leave the source directory untouched.
+        $$(eval $$(call ADD_TARGET_DIR,$${TGT}))
+
+        # A "hook" to build the libtool target.
+        $$(eval $$(call ADD_LIBTOOL_TARGET))
+
+        # Choose the correct linker.
+        ifeq "$$(strip $$(filter $${CXX_SRC_EXTS},$${$${TGT}_SOURCES}))" ""
+            ifeq "$${$${TGT}_LINKER}" ""
+                $${TGT}_LINKER := ${LL}$${LINK.c}
+            endif
+        else
+            ifeq "$${$${TGT}_LINKER}" ""
+                $${TGT}_LINKER := ${LL}$${LINK.cxx}
+            endif
+        endif
+
+        # add rules to build the target
+        $$(eval $$(call ADD_TARGET_RULE$${$${TGT}_SUFFIX},$${TGT}))
+
+        # generate the clean rule for this target.
+        $$(eval $$(call ADD_CLEAN_RULE,$${TGT}))
+
+        # Hook to add an installation target
+        $$(eval $$(call ADD_INSTALL_TARGET,$${TGT}))
+
+        # Hook to add a configuration target
+        $$(eval $$(call ADD_TARGET_CONFIG,$${TGT}))
+
+        # "hook" for legacy Makefiles
+        $$(eval $$(call ADD_LEGACY_RULE,$${TGT}))
+    endif
+
+    TGT := $$(call PEEK,$${TGT_STACK})
+
+    # Reset the "current" directory to it's previous value.
+    DIR_STACK := $$(call POP,$${DIR_STACK})
+    DIR := $$(call PEEK,$${DIR_STACK})
+endef
+
+# MIN - Parameterized "function" that results in the minimum lexical value of
+#   the two values given.
+define MIN
+$(firstword $(sort ${1} ${2}))
+endef
+
+# PEEK - Parameterized "function" that results in the value at the top of the
+#   specified colon-delimited stack.
+define PEEK
+$(lastword $(subst :, ,${1}))
+endef
+
+# POP - Parameterized "function" that pops the top value off of the specified
+#   colon-delimited stack, and results in the new value of the stack. Note that
+#   the popped value cannot be obtained using this function; use peek for that.
+define POP
+${1:%:$(lastword $(subst :, ,${1}))=%}
+endef
+
+# PUSH - Parameterized "function" that pushes a value onto the specified colon-
+#   delimited stack, and results in the new value of the stack.
+define PUSH
+${2:%=${1}:%}
+endef
+
+# QUALIFY_PATH - Given a "root" directory and one or more paths, qualifies the
+#   paths using the "root" directory (i.e. appends the root directory name to
+#   the paths) except for paths that are absolute.
+define QUALIFY_PATH
+$(addprefix ${1}/,$(filter-out /%,${2})) $(filter /%,${2})
+endef
+
+###############################################################################
+#
+# Start of Makefile Evaluation
+#
+###############################################################################
+
+# Older versions of GNU Make lack capabilities needed by boilermake.
+# With older versions, "make" may simply output "nothing to do", likely leading
+# to confusion. To avoid this, check the version of GNU make up-front and
+# inform the user if their version of make doesn't meet the minimum required.
+MIN_MAKE_VERSION := 3.81
+MIN_MAKE_VER_MSG := boilermake requires GNU Make ${MIN_MAKE_VERSION} or greater
+ifeq "${MAKE_VERSION}" ""
+    $(info GNU Make not detected)
+    $(error ${MIN_MAKE_VER_MSG})
+endif
+ifneq "${MIN_MAKE_VERSION}" "$(call MIN,${MIN_MAKE_VERSION},${MAKE_VERSION})"
+    $(info This is GNU Make version ${MAKE_VERSION})
+    $(error ${MIN_MAKE_VER_MSG})
+endif
+
+# Define the source file extensions that we know how to handle.
+OBJ_EXT := o
+C_SRC_EXTS := %.c
+CXX_SRC_EXTS := %.C %.cc %.cp %.cpp %.CPP %.cxx %.c++
+ALL_SRC_EXTS := ${C_SRC_EXTS} ${CXX_SRC_EXTS}
+
+# Initialize global variables.
+ALL_TGTS :=
+DEFS :=
+DIR_STACK :=
+INCDIRS :=
+TGT_STACK :=
+
+ifeq "${top_builddir}" ""
+    top_builddir := .
+endif
+
+# Ensure that valid values are set for BUILD_DIR
+ifeq "$(strip ${BUILD_DIR})" ""
+    ifeq "${top_builddir}" "${PWD}"
+        BUILD_DIR := build
+    else
+        BUILD_DIR := ${top_builddir}/build
+    endif
+else
+    BUILD_DIR := $(call CANONICAL_PATH,${BUILD_DIR})
+endif
+
+# Define compilers and linkers
+#
+COMPILE.c = ${CC}
+COMPILE.cxx = ${CXX}
+CPP = cc -E
+LINK.c = ${CC}
+LINK.cxx = ${CXX}
+
+# Set ECHO to "true" for *very* quiet builds
+ECHO = echo
+
+# Define the "all" target (which simply builds all user-defined targets) as the
+# default goal.
+.PHONY: all
+all: 
+
+# Add "clean" rules to remove all build-generated files.
+.PHONY: clean
+clean:
+
+top_makedir := $(dir $(lastword ${MAKEFILE_LIST}))
+
+-include ${top_makedir}/install.mk
+-include ${top_makedir}/libtool.mk
+
+# Include the main user-supplied submakefile. This also recursively includes
+# all other user-supplied submakefiles.
+$(eval $(call INCLUDE_SUBMAKEFILE,${top_builddir}/main.mk))
+
+# Perform post-processing on global variables as needed.
+DEFS := $(addprefix -D,${DEFS})
+INCDIRS := $(addprefix -I,$(call CANONICAL_PATH,${INCDIRS}))
+
+# Add pattern rule(s) for creating compiled object code from C source.
+$(foreach EXT,${C_SRC_EXTS},\
+  $(eval $(call ADD_OBJECT_RULE,${EXT},$${COMPILE_C_CMDS})))
+
+# Add pattern rule(s) for creating compiled object code from C++ source.
+$(foreach EXT,${CXX_SRC_EXTS},\
+  $(eval $(call ADD_OBJECT_RULE,${EXT},$${COMPILE_CXX_CMDS})))
+
+# Don't include the target dependencies if we're doing a "make clean"
+# Future: have a list of targets that don't require dependency generation,
+#  and see if MAKECMDGOALS is one of them.
+ifneq "$(MAKECMDGOALS)" "clean"
+    $(foreach TGT,${ALL_TGTS},\
+      $(eval -include ${${TGT}_DEPS}))
+endif
diff --git a/scripts/install.mk b/scripts/install.mk
new file mode 100644 (file)
index 0000000..900cea4
--- /dev/null
@@ -0,0 +1,228 @@
+# boilermake: A reusable, but flexible, boilerplate Makefile.
+#
+# Copyright 2008, 2009, 2010 Dan Moulding, Alan T. DeKok
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# ADD_INSTALL_RULE.* - Parameterized "functions" that adds a new
+#   installation to the Makefile.  There should be one ADD_INSTALL_RULE
+#   definition for each type of target that is used in the build.
+#
+#   New rules can be added by copying one of the existing ones, and
+#   replacing the line after the "mkdir"
+#
+
+# ADD_INSTALL_RULE.exe - Parameterized "function" that adds a new rule
+#   and phony target for installing an executable.
+#
+#   USE WITH EVAL
+#
+define ADD_INSTALL_RULE.exe
+    ALL_INSTALL += $${${1}_INSTALLDIR}/$(notdir ${1})
+
+    # Global install depends on ${1}
+    install: $${${1}_INSTALLDIR}/$(notdir ${1})
+
+    # Install executable ${1}
+    $${${1}_INSTALLDIR}/$(notdir ${1}): $${${1}_BUILD}/$${RELINK}${1}
+       @$(ECHO) INSTALL ${1}
+       @$${PROGRAM_INSTALL} -d -m 755 $${${1}_INSTALLDIR}
+       @$${PROGRAM_INSTALL} -c -m 755 $${BUILD_DIR}/bin/$${RELINK}${1} $${${1}_INSTALLDIR}/
+       @$${${1}_POSTINSTALL}
+
+endef
+
+# ADD_INSTALL_RULE.a - Parameterized "function" that adds a new rule
+#   and phony target for installing a static library
+#
+#   USE WITH EVAL
+#
+define ADD_INSTALL_RULE.a
+    ALL_INSTALL += $${${1}_INSTALLDIR}/$(notdir ${1})
+
+    # Global install depends on ${1}
+    install: $${${1}_INSTALLDIR}/$(notdir ${1})
+
+    # Install static library ${1}
+    $${${1}_INSTALLDIR}/$(notdir ${1}): ${1}
+       @$(ECHO) INSTALL ${1}
+       @$${PROGRAM_INSTALL} -d -m 755 $${${1}_INSTALLDIR}
+       @$${PROGRAM_INSTALL} -c -m 755 $${BUILD_DIR}/lib/${1} $${${1}_INSTALLDIR}/
+       @$${${1}_POSTINSTALL}
+
+endef
+
+# ADD_INSTALL_RULE.la - Parameterized "function" that adds a new rule
+#   and phony target for installing a libtool library
+#
+#   FIXME: The libtool install *also* installs a bunch of other files.
+#          ensure that those are removed, too.
+#
+#   USE WITH EVAL
+#
+define ADD_INSTALL_RULE.la
+    ALL_INSTALL += $${${1}_INSTALLDIR}/$(notdir ${1})
+
+    # Global install depends on ${1}
+    install: $${${1}_INSTALLDIR}/$(notdir ${1})
+
+    # Install libtool library ${1}
+    $${${1}_INSTALLDIR}/$(notdir ${1}): $${${1}_BUILD}/$${RELINK}${1}
+       @$(ECHO) INSTALL ${1}
+       @$${PROGRAM_INSTALL} -d -m 755 $${${1}_INSTALLDIR}
+       @$${PROGRAM_INSTALL} -c -m 755 $${BUILD_DIR}/lib/$${RELINK}${1} $${${1}_INSTALLDIR}/
+       @$${${1}_POSTINSTALL}
+
+endef
+
+# ADD_INSTALL_RULE.man - Parameterized "function" that adds a new rule
+#   and phony target for installing a "man" page.  It will take care of
+#   installing it into the correct subdirectory of "man".
+#
+#   USE WITH EVAL
+#
+define ADD_INSTALL_RULE.man
+    ALL_INSTALL += ${2}/$(notdir ${1})
+
+    # Global install depends on ${1}
+    install: ${2}/$(notdir ${1})
+
+    # Install manual page ${1}
+    ${2}/$(notdir ${1}): ${1} ${2}
+       @$(ECHO) INSTALL ${1}
+       @$${PROGRAM_INSTALL} -c -m 644 ${1} ${2}/
+
+endef
+
+
+# ADD_INSTALL_TARGET - Parameterized "function" that adds a new rule
+#   which installs everything for the target.
+#
+#   USE WITH EVAL
+#
+define ADD_INSTALL_TARGET
+    # Figure out which target rule to use for installation.
+    ifeq "$${${1}_SUFFIX}" ".exe"
+        ifeq "$${TGT_INSTALLDIR}" ".."
+            TGT_INSTALLDIR := $${bindir}
+        endif
+    else 
+        ifeq "$${TGT_INSTALLDIR}" ".."
+            TGT_INSTALLDIR := $${libdir}
+        endif
+    endif
+
+    ${1}_INSTALLDIR := ${LL}$${DESTDIR}$${TGT_INSTALLDIR}
+
+    # add rules to install the target
+    ifneq "$${${1}_INSTALLDIR}" ""
+        $$(eval $$(call ADD_INSTALL_RULE$${${1}_SUFFIX},${1}))
+    endif
+
+    # add rules to install the MAN pages.
+    ifneq "$$(strip $${${1}_MAN})" ""
+        ifeq "$${mandir}" ""
+            $$(error You must define 'mandir' in order to be able to install MAN pages.)
+        endif
+
+        MAN := $$(call QUALIFY_PATH,$${DIR},$${MAN})
+        MAN := $$(call CANONICAL_PATH,$${MAN})
+
+        $$(foreach PAGE,$${MAN},\
+            $$(eval $$(call ADD_INSTALL_RULE.man,$${PAGE},\
+              $${DESTDIR}$${mandir}/man$$(subst .,,$$(suffix $${PAGE})))))
+    endif
+endef
+
+.PHONY: install
+install:
+
+ALL_INSTALL :=
+
+# Define reasonable defaults for all of the installation directories.
+# The user can over-ride these, but these are the defaults.
+ifeq "${prefix}" ""
+    prefix = /usr/local
+endif
+ifeq "${exec_prefix}" ""
+    exec_prefix = ${prefix}
+endif
+ifeq "${bindir}" ""
+    bindir = ${exec_prefix}/bin
+endif
+ifeq "${sbindir}" ""
+    sbindir = ${exec_prefix}/sbin
+endif
+ifeq "${libdir}" ""
+    libdir = ${exec_prefix}/lib
+endif
+ifeq "${sysconfdir}" ""
+    sysconfdir = ${prefix}/etc
+endif
+ifeq "${localstatedir}" ""
+    localstatedir = ${prefix}/var
+endif
+ifeq "${datarootdir}" ""
+    datarootdir = ${prefix}/share
+endif
+ifeq "${datadir}" ""
+    datadir = ${prefix}/share
+endif
+ifeq "${mandir}" ""
+    mandir = ${datadir}/man
+endif
+ifeq "${docdir}" ""
+    ifneq "${PROJECT_NAME}" ""
+        docdir = ${datadir}/doc/${PROJECT_NAME}
+    endif
+endif
+ifeq "${logdir}" ""
+    logdir = ${localstatedir}/log/
+endif
+ifeq "${includedir}" ""
+    includedir = ${prefix}/include
+endif
+
+
+# Un-install any installed programs.  We DON'T want to depend on the
+# install target.  Doing so would cause "make uninstall" to build it,
+# install it, and then remove it.
+#
+# We also want to uninstall only when there are "install_foo" targets.
+.PHONY: uninstall
+uninstall:
+       @rm -f ${ALL_INSTALL} ./.no_such_file
+
+# Wrapper around INSTALL
+ifeq "${PROGRAM_INSTALL}" ""
+    PROGRAM_INSTALL := ${INSTALL}
+
+endif
+
+# Make just the installation directories
+.PHONY: installdirs
+installdirs:
+
+# Be nice to the user.  If there is no INSTALL program, then print out
+# a helpful message.  Without this check, the "install" rules defined
+# above would try to run a command-line with a blank INSTALL, and give
+# some inscrutable error.
+ifeq "${INSTALL}" ""
+install: install_ERROR
+
+.PHONY: install_ERROR
+install_ERROR:
+       @$(ECHO) Please define INSTALL in order to enable the installation rules.
+       @exit 1
+endif
diff --git a/scripts/jlibtool.c b/scripts/jlibtool.c
new file mode 100644 (file)
index 0000000..5d007fc
--- /dev/null
@@ -0,0 +1,2185 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#if !defined(__MINGW32__)
+#include <sys/wait.h>
+#endif
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+#include <assert.h>
+
+#ifdef __EMX__
+#  define SHELL_CMD  "sh"
+#  define GEN_EXPORTS "emxexp"
+#  define DEF2IMPLIB_CMD "emximp"
+#  define SHARE_SW   "-Zdll -Zmtd"
+#  define USE_OMF 1
+#  define TRUNCATE_DLL_NAME
+#  define DYNAMIC_LIB_EXT "dll"
+#  define EXE_EXT ".exe"
+
+#  if USE_OMF
+     /* OMF is the native format under OS/2 */
+#    define STATIC_LIB_EXT "lib"
+#    define OBJECT_EXT     "obj"
+#    define LIBRARIAN      "emxomfar"
+#    define LIBRARIAN_OPTS "cr"
+#  else
+     /* but the alternative, a.out, can fork() which is sometimes necessary */
+#    define STATIC_LIB_EXT "a"
+#    define OBJECT_EXT     "o"
+#    define LIBRARIAN      "ar"
+#    define LIBRARIAN_OPTS "cr"
+#  endif
+#endif
+
+#if defined(__APPLE__)
+#  define SHELL_CMD  "/bin/sh"
+#  define DYNAMIC_LIB_EXT "dylib"
+#  define MODULE_LIB_EXT  "bundle"
+#  define STATIC_LIB_EXT "a"
+#  define OBJECT_EXT     "o"
+#  define LIBRARIAN      "ar"
+#  define LIBRARIAN_OPTS "cr"
+/* man libtool(1) documents ranlib option of -c.  */
+#  define RANLIB "ranlib"
+#  define PIC_FLAG "-fPIC -fno-common"
+#  define SHARED_OPTS "-dynamiclib"
+#  define MODULE_OPTS "-bundle -dynamic"
+#  define DYNAMIC_LINK_OPTS "-flat_namespace"
+#  define DYNAMIC_LINK_UNDEFINED "-undefined suppress"
+#  define dynamic_link_version_func darwin_dynamic_link_function
+#  define DYNAMIC_INSTALL_NAME "-install_name"
+#  define DYNAMIC_LINK_NO_INSTALL "-dylib_file"
+#  define HAS_REALPATH
+/*-install_name  /Users/jerenk/apache-2.0-cvs/lib/libapr.0.dylib -compatibility_version 1 -current_version 1.0 */
+#  define LD_LIBRARY_PATH "DYLD_LIBRARY_PATH"
+#  define LD_LIBRARY_PATH_LOCAL "DYLD_FALLBACK_LIBRARY_PATH"
+#endif
+
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
+#  define SHELL_CMD  "/bin/sh"
+#  define DYNAMIC_LIB_EXT "so"
+#  define MODULE_LIB_EXT  "so"
+#  define STATIC_LIB_EXT "a"
+#  define OBJECT_EXT     "o"
+#  define LIBRARIAN      "ar"
+#  define LIBRARIAN_OPTS "cr"
+#  define RANLIB "ranlib"
+#  define PIC_FLAG "-fPIC"
+#  define RPATH "-rpath"
+#  define SHARED_OPTS "-shared"
+#  define MODULE_OPTS "-shared"
+#  define DYNAMIC_LINK_OPTS "-export-dynamic"
+#  define LINKER_FLAG_PREFIX "-Wl,"
+#  define ADD_MINUS_L
+#  define LD_RUN_PATH "LD_RUN_PATH"
+#  define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
+#  define LD_LIBRARY_PATH_LOCAL LD_LIBRARY_PATH
+#endif
+
+#if defined(sun)
+#  define SHELL_CMD  "/bin/sh"
+#  define DYNAMIC_LIB_EXT "so"
+#  define MODULE_LIB_EXT  "so"
+#  define STATIC_LIB_EXT "a"
+#  define OBJECT_EXT     "o"
+#  define LIBRARIAN      "ar"
+#  define LIBRARIAN_OPTS "cr"
+#  define RANLIB "ranlib"
+#  define PIC_FLAG "-KPIC"
+#  define RPATH "-R"
+#  define SHARED_OPTS "-G"
+#  define MODULE_OPTS "-G"
+#  define DYNAMIC_LINK_OPTS ""
+#  define LINKER_FLAG_NO_EQUALS
+#  define ADD_MINUS_L
+#  define HAS_REALPATH
+#  define LD_RUN_PATH "LD_RUN_PATH"
+#  define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
+#  define LD_LIBRARY_PATH_LOCAL LD_LIBRARY_PATH
+#endif
+
+#if defined(_OSD_POSIX)
+#  define SHELL_CMD  "/usr/bin/sh"
+#  define DYNAMIC_LIB_EXT "so"
+#  define MODULE_LIB_EXT  "so"
+#  define STATIC_LIB_EXT "a"
+#  define OBJECT_EXT     "o"
+#  define LIBRARIAN      "ar"
+#  define LIBRARIAN_OPTS "cr"
+#  define SHARED_OPTS "-G"
+#  define MODULE_OPTS "-G"
+#  define LINKER_FLAG_PREFIX "-Wl,"
+#  define NEED_SNPRINTF
+#endif
+
+#if defined(sinix) && defined(mips) && defined(__SNI_TARG_UNIX)
+#  define SHELL_CMD  "/usr/bin/sh"
+#  define DYNAMIC_LIB_EXT "so"
+#  define MODULE_LIB_EXT  "so"
+#  define STATIC_LIB_EXT "a"
+#  define OBJECT_EXT     "o"
+#  define LIBRARIAN      "ar"
+#  define LIBRARIAN_OPTS "cr"
+#  define RPATH "-Brpath"
+#  define SHARED_OPTS "-G"
+#  define MODULE_OPTS "-G"
+#  define DYNAMIC_LINK_OPTS "-Wl,-Blargedynsym"
+#  define LINKER_FLAG_PREFIX "-Wl,"
+#  define NEED_SNPRINTF
+#  define LD_RUN_PATH "LD_RUN_PATH"
+#  define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
+#  define LD_LIBRARY_PATH_LOCAL LD_LIBRARY_PATH
+#endif
+
+#if defined(__MINGW32__)
+#  define SHELL_CMD "sh"
+#  define DYNAMIC_LIB_EXT "dll"
+#  define MODULE_LIB_EXT  "dll"
+#  define STATIC_LIB_EXT "a"
+#  define OBJECT_EXT     "o"
+#  define LIBRARIAN      "ar"
+#  define LIBRARIAN_OPTS "cr"
+#  define RANLIB "ranlib"
+#  define LINKER_FLAG_PREFIX "-Wl,"
+#  define SHARED_OPTS "-shared"
+#  define MODULE_OPTS "-shared"
+#  define MKDIR_NO_UMASK
+#  define EXE_EXT ".exe"
+#endif
+
+#define OBJDIR ".libs"
+
+#ifndef SHELL_CMD
+#error Unsupported platform: Please add defines for SHELL_CMD etc. for your platform.
+#endif
+
+#ifdef NEED_SNPRINTF
+#include <stdarg.h>
+#endif
+
+#ifdef __EMX__
+#include <process.h>
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+
+/* We want to say we are libtool 1.4 for shlibtool compatibility. */
+#define VERSION "1.4"
+
+enum tool_mode_t {
+    mUnknown,
+    mCompile,
+    mLink,
+    mExecute,
+    mInstall,
+};
+
+enum output_t {
+    otGeneral,
+    otObject,
+    otProgram,
+    otLibrary,
+    otStaticLibraryOnly,
+    otDynamicLibraryOnly,
+    otModule,
+};
+
+enum pic_mode_e {
+    pic_UNKNOWN,
+    pic_PREFER,
+    pic_AVOID,
+};
+
+enum shared_mode_e {
+    share_UNSET,
+    share_STATIC,
+    share_SHARED,
+};
+
+enum lib_type {
+    type_UNKNOWN,
+    type_DYNAMIC_LIB,
+    type_STATIC_LIB,
+    type_MODULE_LIB,
+    type_OBJECT,
+};
+
+typedef struct {
+    const char **vals;
+    int num; 
+} count_chars;
+
+typedef struct {
+    const char *normal;
+    const char *install;
+} library_name;
+
+typedef struct {
+    count_chars *normal;
+    count_chars *install;
+    count_chars *dependencies;
+} library_opts;
+
+typedef struct {
+    int silent;
+    int debug;
+    enum shared_mode_e shared;
+    int export_all;
+    int dry_run;
+    enum pic_mode_e pic_mode;
+    int export_dynamic;
+    int no_install;
+} options_t;
+
+typedef struct {
+    enum tool_mode_t mode;
+    enum output_t output;
+    options_t options;
+
+    char *output_name;
+    char *fake_output_name;
+    char *basename;
+
+    const char *install_path;
+    const char *compiler;
+    const char *program;
+    count_chars *program_opts;
+
+    count_chars *arglist;
+    count_chars *tmp_dirs;
+    count_chars *obj_files;
+    count_chars *dep_rpaths;
+    count_chars *rpaths;
+
+    library_name static_name;
+    library_name shared_name;
+    library_name module_name;
+
+    library_opts static_opts;
+    library_opts shared_opts;
+
+    const char *version_info;
+    const char *undefined_flag;
+} command_t;
+
+#ifdef RPATH
+static void add_rpath(count_chars *cc, const char *path);
+#endif
+
+static void usage(int code)
+{
+       printf("Usage: jlibtool [OPTIONS...] COMMANDS...\n");
+       printf("jlibtool is a replacement for GNU libtool with similar functionality.\n\n");
+
+       printf("    --config          show all configuration variables\n");
+       printf("    --debug           enable verbose shell tracing\n");
+       printf("    --dry-run         display commands without modifying any files\n");
+       printf("    --help            display this help message and exit\n");
+       printf("    --mode=MODE       use operational mode MODE (you *must* set mode)\n");
+
+       printf("    --silent          don't print informational messages\n");
+       printf("    --tag=TAG         Ignored for libtool compatibility\n");
+       printf("    --version         print version information\n");
+
+
+       printf("    --shared          Build shared libraries when using --mode=link\n");
+       printf("    --export-all      Try to export 'def' file on some platforms\n");
+
+       printf("\nMODE must be one of the following:\n\n");
+       printf("      compile         compile a source file into a jlibtool object\n");
+       printf("      execute         automatically set library path, then run a program\n");
+        printf("      install         install libraries or executables\n");
+        printf("      link            create a library or an executable\n");
+
+       printf("\nMODE-ARGS can be the following:\n\n");
+       printf("      -export-dynamic  accepted and ignored\n");
+       printf("      -module          create a module when linking\n");
+       printf("      -shared          create a shared library when linking\n");
+       printf("      -prefer-pic      prefer position-independent-code when compiling\n");
+       printf("      -prefer-non-pic  prefer non position-independent-code when compiling\n");
+       printf("      -static          create a static library when linking\n");
+       printf("      -no-install      link libraries locally\n");
+       printf("      -l arg           pass '-l arg' to the link stage\n");
+       printf("      -L arg           pass '-L arg' to the link stage\n");
+       printf("      -R dir           add 'dir' to runtime library search path.\n");
+       printf("      -Zexe            accepted and ignored\n");
+       printf("      -avoid-version   accepted and ignored\n");
+
+       exit(code);
+}
+
+#if defined(NEED_SNPRINTF)
+/* Write at most n characters to the buffer in str, return the
+ * number of chars written or -1 if the buffer would have been
+ * overflowed.
+ *
+ * This is portable to any POSIX-compliant system has /dev/null
+ */
+static FILE *f=NULL;
+static int vsnprintf( char *str, size_t n, const char *fmt, va_list ap )
+{
+       int res;
+
+       if (f == NULL)
+               f = fopen("/dev/null","w");
+       if (f == NULL)
+               return -1;
+
+       setvbuf( f, str, _IOFBF, n );
+
+       res = vfprintf( f, fmt, ap );
+
+       if ( res > 0 && res < n ) {
+               res = vsprintf( str, fmt, ap );
+       }
+       return res;
+}
+static int snprintf( char *str, size_t n, const char *fmt, ... )
+{
+        va_list ap;
+        int res;
+        va_start( ap, fmt );
+        res = vsnprintf( str, n, fmt, ap );
+        va_end( ap );
+        return res;
+}
+#endif
+
+static void init_count_chars(count_chars *cc)
+{
+    cc->vals = (const char**)malloc(PATH_MAX*sizeof(char*));
+    cc->num = 0;
+}
+
+static void clear_count_chars(count_chars *cc)
+{
+    int i;
+    for (i = 0; i < cc->num; i++) {
+        cc->vals[i] = 0;
+    }
+
+    cc->num = 0;
+}
+
+static void push_count_chars(count_chars *cc, const char *newval)
+{
+    cc->vals[cc->num++] = newval;
+}
+
+static void pop_count_chars(count_chars *cc)
+{
+    cc->num--;
+}
+
+static void insert_count_chars(count_chars *cc, const char *newval, int position)
+{
+    int i;
+
+    for (i = cc->num; i > position; i--) {
+        cc->vals[i] = cc->vals[i-1];
+    }
+
+    cc->vals[position] = newval;
+    cc->num++;
+}
+
+static void append_count_chars(count_chars *cc, count_chars *cctoadd)
+{
+    int i;
+    for (i = 0; i < cctoadd->num; i++) {
+        if (cctoadd->vals[i]) {
+            push_count_chars(cc, cctoadd->vals[i]);
+        }
+    }
+}
+
+static const char *flatten_count_chars(count_chars *cc, int space)
+{
+    int i, size;
+    char *newval;
+
+    size = 0;
+    for (i = 0; i < cc->num; i++) {
+        if (cc->vals[i]) {
+            size += strlen(cc->vals[i]) + 1;
+            if (space) {
+              size++;
+            }
+        }
+    }
+
+    newval = (char*)malloc(size + 1);
+    newval[0] = 0;
+
+    for (i = 0; i < cc->num; i++) {
+        if (cc->vals[i]) {
+            strcat(newval, cc->vals[i]);
+            if (space) {
+                strcat(newval, " ");
+            }
+        }
+    }
+
+    return newval;
+}
+
+static char *shell_esc(const char *str)
+{
+    int in_quote = 0;
+    char *cmd;
+    unsigned char *d;
+    const unsigned char *s;
+
+    cmd = (char *)malloc(2 * strlen(str) + 3);
+    d = (unsigned char *)cmd;
+    s = (const unsigned char *)str;
+
+#ifdef __MINGW32__
+    *d++ = '\"';
+#endif
+
+    for (; *s; ++s) {
+        if (*s == '"') {
+            *d++ = '\\';
+            in_quote++;
+        }
+        else if (*s == '\\' || (*s == ' ' && (in_quote % 2))) {
+            *d++ = '\\';
+        }
+        *d++ = *s;
+    }
+
+#ifdef __MINGW32__
+    *d++ = '\"';
+#endif
+
+    *d = '\0';
+    return cmd;
+}
+
+static int external_spawn(command_t *cmd, const char *file, const char **argv)
+{
+    if (!cmd->options.silent) {
+        const char **argument = argv;
+       //        printf("Executing: ");
+        while (*argument) {
+            printf("%s ", *argument);
+            argument++;
+        }
+        puts("");
+    }
+
+    if (cmd->options.dry_run) {
+        return 0;
+    }
+#if defined(__EMX__) || defined(__MINGW32__)
+    return spawnvp(P_WAIT, argv[0], argv);
+#else
+    {
+        pid_t pid;
+        pid = fork();
+        if (pid == 0) {
+            return execvp(argv[0], (char**)argv);
+        }
+        else {
+            int statuscode;
+            waitpid(pid, &statuscode, 0);
+            if (WIFEXITED(statuscode)) {
+                return WEXITSTATUS(statuscode);
+            }
+            return 0;
+        }
+    }
+#endif
+}
+
+static int run_command(command_t *cmd_data, count_chars *cc)
+{
+    char *command;
+    const char *spawn_args[4];
+    count_chars tmpcc;
+
+    init_count_chars(&tmpcc);
+
+    if (cmd_data->program) {
+        push_count_chars(&tmpcc, cmd_data->program);
+    }
+
+    append_count_chars(&tmpcc, cmd_data->program_opts);
+
+    append_count_chars(&tmpcc, cc);
+
+    command = shell_esc(flatten_count_chars(&tmpcc, 1));
+
+    spawn_args[0] = SHELL_CMD;
+    spawn_args[1] = "-c";
+    spawn_args[2] = command;
+    spawn_args[3] = NULL;
+
+    return external_spawn(cmd_data, spawn_args[0], (const char**)spawn_args);
+}
+
+/*
+ * print configuration
+ * shlibpath_var is used in configure.
+ */
+#define printc(_x,_y) printf(_x "=\"%s\"\n", _y)
+
+static void print_config(void)
+{
+#ifdef LD_RUN_PATH
+    printc("runpath_var", LD_RUN_PATH);
+#endif
+#ifdef LD_LIBRARY_PATH
+    printc("shlibpath_var", LD_LIBRARY_PATH);
+#endif
+#ifdef LD_LIBRARY_PATH_LOCAL
+    printc("shlocallibpath_var", LD_LIBRARY_PATH_LOCAL);
+#endif
+#ifdef SHELL_CMD
+    printc("SHELL", SHELL_CMD);
+#endif
+#ifdef OBJECT_EXT
+    printc("objext", OBJECT_EXT);
+#endif
+#ifdef OBJDIR
+    printc("objdir", OBJDIR);
+#endif
+#ifdef DYNAMIC_LIB_EXT
+    /* add a '.' prefix because libtool does that. */
+    printc("shrext_cmds", "echo ." DYNAMIC_LIB_EXT);
+    /* add a '.' prefix because libtool does that. */
+    printc("shrext", "." DYNAMIC_LIB_EXT);
+#endif
+#ifdef EXE_EXT
+    printc("exeext", EXE_EXT);
+#endif
+#ifdef STATIC_LIB_EXT
+    printc("libext", STATIC_LIB_EXT);
+#endif
+#ifdef LIBRARIAN
+    printc("AR", LIBRARIAN);
+#endif
+#ifdef LIBRARIAN_OPTS
+    printc("AR_FLAGS", LIBRARIAN_OPTS);
+#endif
+#ifdef LINKER_FLAG_PREFIX
+    printc("wl", LINKER_FLAG_PREFIX);
+#endif
+#ifdef RANLIB
+    printc("ranlib", RANLIB);
+#endif
+}
+/*
+ * Add a directory to the runtime library search path.
+ */
+static void add_runtimedirlib(char *arg, command_t *cmd_data)
+{
+#ifdef RPATH
+    add_rpath(cmd_data->shared_opts.dependencies, arg);
+#else
+#endif
+}
+
+static int parse_long_opt(char *arg, command_t *cmd_data)
+{
+    char *equal_pos = strchr(arg, '=');
+    char var[50];
+    char value[500];
+
+    if (equal_pos) {
+        strncpy(var, arg, equal_pos - arg);
+        var[equal_pos - arg] = 0;
+        strcpy(value, equal_pos + 1);
+    } else {
+        strcpy(var, arg);
+    }
+
+    if (strcmp(var, "silent") == 0) {
+        cmd_data->options.silent = 1;
+    } else if (strcmp(var, "debug") == 0) {
+        cmd_data->options.debug = 1;
+    } else if (strcmp(var, "mode") == 0) {
+        if (strcmp(value, "compile") == 0) {
+            cmd_data->mode = mCompile;
+            cmd_data->output = otObject;
+
+        } else if (strcmp(value, "link") == 0) {
+            cmd_data->mode = mLink;
+            cmd_data->output = otLibrary;
+
+       } else if (strcmp(value, "install") == 0) {
+            cmd_data->mode = mInstall;
+
+       } else if (strcmp(value, "execute") == 0) {
+            cmd_data->mode = mExecute;
+
+        } else {
+           printf("Unknown mode \"%s\"\n", value);
+       }
+    } else if (strcmp(var, "shared") == 0) {
+      if ((cmd_data->mode == mLink) &&
+         (cmd_data->output == otGeneral)) {
+            cmd_data->output = otDynamicLibraryOnly;
+       }
+        cmd_data->options.shared = share_SHARED;
+    } else if (strcmp(var, "export-all") == 0) {
+        cmd_data->options.export_all = 1;
+    } else if (strcmp(var, "dry-run") == 0) {
+        printf("Dry-run mode on!\n");
+        cmd_data->options.dry_run = 1;
+    } else if (strcmp(var, "version") == 0) {
+        printf("Version " VERSION "\n");
+    } else if (strcmp(var, "help") == 0) {
+       usage(0);
+    } else if (strcmp(var, "config") == 0) {
+        print_config();
+    } else if (strcmp(var, "tag") == 0) {
+        if (strcmp(value, "CC") == 0) {
+            /* Do nothing. */
+        }
+        if (strcmp(value, "CXX") == 0) {
+            /* Do nothing. */
+        }
+    } else {
+        return 0;
+    }
+
+    return 1;
+}
+
+/* Return 1 if we eat it. */
+static int parse_short_opt(char *arg, command_t *cmd_data)
+{
+    if (strcmp(arg, "export-dynamic") == 0) {
+        cmd_data->options.export_dynamic = 1;
+        return 1;
+    }
+
+    if (strcmp(arg, "module") == 0) {
+        cmd_data->output = otModule;
+        return 1;
+    }
+
+    if (strcmp(arg, "shared") == 0) {
+        if (cmd_data->mode == mLink) {
+            cmd_data->output = otDynamicLibraryOnly;
+        }
+        cmd_data->options.shared = share_SHARED;
+        return 1;
+    }
+
+    if (strcmp(arg, "Zexe") == 0) {
+        return 1;
+    }
+
+    if (strcmp(arg, "avoid-version") == 0) {
+        return 1;
+    }
+
+    if (strcmp(arg, "prefer-pic") == 0) {
+        cmd_data->options.pic_mode = pic_PREFER;
+        return 1;
+    }
+
+    if (strcmp(arg, "prefer-non-pic") == 0) {
+        cmd_data->options.pic_mode = pic_AVOID;
+        return 1;
+    }
+
+    if (strcmp(arg, "static") == 0) {
+        cmd_data->options.shared = share_STATIC;
+        return 1;
+    }
+
+    if (cmd_data->mode == mLink) {
+        if (strcmp(arg, "no-install") == 0) {
+            cmd_data->options.no_install = 1;
+            return 1;
+        }
+        if (arg[0] == 'L' || arg[0] == 'l') {
+            /* Hack... */
+            arg--;
+            push_count_chars(cmd_data->shared_opts.dependencies, arg);
+            return 1;
+        } else if (arg[0] == 'R' && arg[1]) {
+            /* -Rdir Add dir to runtime library search path. */
+            add_runtimedirlib(&arg[1], cmd_data);
+            return 1;
+        }
+    }
+    return 0;
+}
+
+static char *truncate_dll_name(char *path)
+{
+    /* Cut DLL name down to 8 characters after removing any mod_ prefix */
+    char *tmppath = strdup(path);
+    char *newname = strrchr(tmppath, '/') + 1;
+    char *ext = strrchr(newname, '.');
+    int len;
+
+    if (ext == NULL)
+        return tmppath;
+
+    len = ext - newname;
+
+    if (strncmp(newname, "mod_", 4) == 0) {
+        strcpy(newname, newname + 4);
+        len -= 4;
+    }
+
+    if (len > 8) {
+        strcpy(newname + 8, strchr(newname, '.'));
+    }
+
+    return tmppath;
+}
+
+static long safe_strtol(const char *nptr, const char **endptr, int base)
+{
+    long rv;
+
+    errno = 0;
+
+    rv = strtol(nptr, (char**)endptr, 10);
+
+    if (errno == ERANGE) {
+        return 0;
+    }
+
+    return rv; 
+}
+
+static void safe_mkdir(const char *path)
+{
+    mode_t old_umask;
+
+    old_umask = umask(0);
+    umask(old_umask);
+
+#ifdef MKDIR_NO_UMASK
+    mkdir(path);
+#else
+    mkdir(path, ~old_umask);
+#endif
+}
+
+/* returns just a file's name without the path */
+static const char *jlibtool_basename(const char *fullpath)
+{
+    const char *name = strrchr(fullpath, '/');
+
+    if (name == NULL) {
+        name = strrchr(fullpath, '\\');
+    }
+
+    if (name == NULL) {
+        name = fullpath;
+    } else {
+        name++;
+    }
+
+    return name;
+}
+
+/* returns just a file's name without path or extension */
+static const char *nameof(const char *fullpath)
+{
+    const char *name;
+    const char *ext;
+
+    name = jlibtool_basename(fullpath);
+    ext = strrchr(name, '.');
+
+    if (ext) {
+        char *trimmed;
+        trimmed = malloc(ext - name + 1);
+        strncpy(trimmed, name, ext - name);
+        trimmed[ext-name] = 0;
+        return trimmed;
+    }
+
+    return name;
+}
+
+/* version_info is in the form of MAJOR:MINOR:PATCH */
+static const char *darwin_dynamic_link_function(const char *version_info)
+{
+    char *newarg;
+    long major, minor, patch;
+
+    major = 0;
+    minor = 0;
+    patch = 0;
+
+    if (version_info) {
+        major = safe_strtol(version_info, &version_info, 10);
+
+        if (version_info) {
+            if (version_info[0] == ':') {
+                version_info++;
+            }
+
+            minor = safe_strtol(version_info, &version_info, 10);
+
+            if (version_info) {
+                if (version_info[0] == ':') {
+                    version_info++;
+                }
+
+                patch = safe_strtol(version_info, &version_info, 10);
+
+            }
+        }
+    }
+
+    /* Avoid -dylib_compatibility_version must be greater than zero errors. */
+    if (major == 0) {
+        major = 1;
+    }
+    newarg = (char*)malloc(100);
+    snprintf(newarg, 99,
+             "-compatibility_version %ld -current_version %ld.%ld",
+             major, major, minor);
+
+    return newarg;
+}
+
+
+/*
+ *     Add a '.libs/' to the buffer.  The caller ensures that
+ *     The buffer is large enough to handle 6 extra characters.
+ */
+static void add_dotlibs(char *buffer)
+{
+       char *name = strrchr(buffer, '/');
+
+       if (!name) {
+               if (!buffer[0]) {
+                       strcpy(buffer, ".libs/");
+                       return;
+               }
+               name = buffer;
+       } else {
+               name++;
+       }
+       memmove(name + 6, name, strlen(name));
+       memcpy(name, ".libs/", 6);
+}
+
+/* genlib values
+ * 0 - static
+ * 1 - dynamic
+ * 2 - module
+ */
+static char *gen_library_name(const char *name, int genlib)
+{
+    char *newarg, *newext;
+
+    newarg = (char *)malloc(strlen(name) + 11);
+
+    if (genlib == 2 && strncmp(name, "lib", 3) == 0) {
+        name += 3;
+    }
+
+    if (genlib == 2) {
+        strcat(newarg, jlibtool_basename(name));
+    }
+    else {
+        strcat(newarg, name);
+    }
+
+    newext = strrchr(newarg, '.') + 1;
+
+    switch (genlib) {
+    case 0:
+        strcpy(newext, STATIC_LIB_EXT);
+        break;
+    case 1:
+        strcpy(newext, DYNAMIC_LIB_EXT);
+        break;
+    case 2:
+        strcpy(newext, MODULE_LIB_EXT);
+        break;
+    }
+
+    add_dotlibs(newarg);
+
+    return newarg;
+}
+
+/* genlib values
+ * 0 - static
+ * 1 - dynamic
+ * 2 - module
+ */
+static char *gen_install_name(const char *name, int genlib)
+{
+    struct stat sb;
+    char *newname;
+    int rv;
+
+    newname = gen_library_name(name, genlib);
+
+    /* Check if it exists. If not, return NULL.  */
+    rv = stat(newname, &sb);
+
+    if (rv) {
+        return NULL;
+    }
+
+    return newname;
+}
+
+static char *check_object_exists(command_t *cmd, const char *arg, int arglen)
+{
+    char *newarg, *ext;
+    int pass, rv;
+
+    newarg = (char *)malloc(arglen + 10);
+    memcpy(newarg, arg, arglen);
+    newarg[arglen] = 0;
+    ext = newarg + arglen;
+
+    pass = 0;
+
+    do {
+        struct stat sb;
+
+        switch (pass) {
+        case 0:
+            strcpy(ext, OBJECT_EXT);
+            break;
+/*
+        case 1:
+            strcpy(ext, NO_PIC_EXT);
+            break;
+*/
+        default:
+            break;
+        } 
+
+        if (cmd->options.debug) {
+            printf("Checking (obj): %s\n", newarg);
+        }
+        rv = stat(newarg, &sb);
+    }
+    while (rv != 0 && ++pass < 1);
+
+    if (rv == 0) {
+        if (pass == 1) {
+            cmd->options.pic_mode = pic_AVOID;
+        }
+        return newarg;
+    }
+
+    return NULL;
+}
+
+/* libdircheck values:
+ * 0 - no .libs suffix
+ * 1 - .libs suffix
+ */
+static char *check_library_exists(command_t *cmd, const char *arg, int pathlen,
+                           int libdircheck, enum lib_type *libtype)
+{
+    char *newarg, *ext;
+    int pass, rv, newpathlen;
+
+    newarg = (char *)malloc(strlen(arg) + 10);
+    strcpy(newarg, arg);
+    newarg[pathlen] = 0;
+
+    newpathlen = pathlen;
+    if (libdircheck) {
+        add_dotlibs(newarg);
+        newpathlen += sizeof(".libs/") - 1;
+    }
+
+    strcpy(newarg+newpathlen, arg+pathlen);
+    ext = strrchr(newarg, '.') + 1;
+
+    pass = 0;
+
+    do {
+        struct stat sb;
+
+        switch (pass) {
+        case 0:
+            if (cmd->options.pic_mode != pic_AVOID &&
+                cmd->options.shared != share_STATIC) {
+                strcpy(ext, DYNAMIC_LIB_EXT);
+                *libtype = type_DYNAMIC_LIB;
+                break;
+            }
+            pass = 1;
+            /* Fall through */
+        case 1:
+            strcpy(ext, STATIC_LIB_EXT);
+            *libtype = type_STATIC_LIB;
+            break;
+        case 2:
+            strcpy(ext, MODULE_LIB_EXT);
+            *libtype = type_MODULE_LIB;
+            break;
+        case 3:
+            strcpy(ext, OBJECT_EXT);
+            *libtype = type_OBJECT;
+            break;
+        default:
+            *libtype = type_UNKNOWN;
+            break;
+        } 
+
+        if (cmd->options.debug) {
+            printf("Checking (lib): %s\n", newarg);
+        }
+        rv = stat(newarg, &sb);
+    }
+    while (rv != 0 && ++pass < 4);
+
+    if (rv == 0) {
+        return newarg;
+    }
+
+    return NULL;
+}
+
+static char * load_install_path(const char *arg)
+{
+    FILE *f;
+    char *path;
+
+    path = malloc(PATH_MAX);
+
+    f = fopen(arg,"r");
+    if (f == NULL) {
+        return NULL;
+    }
+    fgets(path, PATH_MAX, f);
+    fclose(f);
+    if (path[strlen(path)-1] == '\n') {
+        path[strlen(path)-1] = '\0';
+    }
+    /* Check that we have an absolute path.
+     * Otherwise the file could be a GNU libtool file.
+     */
+    if (path[0] != '/') {
+        return NULL;
+    }
+    return path;
+}
+
+static char * load_noinstall_path(const char *arg, int pathlen)
+{
+    char *newarg, *expanded_path;
+    int newpathlen;
+
+    newarg = (char *)malloc(strlen(arg) + 10);
+    strcpy(newarg, arg);
+    newarg[pathlen] = 0;
+
+    newpathlen = pathlen;
+    strcat(newarg, ".libs");
+    newpathlen += sizeof(".libs") - 1;
+    newarg[newpathlen] = 0;
+
+#ifdef HAS_REALPATH
+    expanded_path = malloc(PATH_MAX);
+    expanded_path = realpath(newarg, expanded_path);
+    /* Uh, oh.  There was an error.  Fall back on our first guess. */
+    if (!expanded_path) {
+        expanded_path = newarg;
+    }
+#else
+    /* We might get ../ or something goofy.  Oh, well. */
+    expanded_path = newarg;
+#endif
+
+    return expanded_path;
+}
+
+static void add_dynamic_link_opts(command_t *cmd_data, count_chars *args)
+{
+#ifdef DYNAMIC_LINK_OPTS
+    if (cmd_data->options.pic_mode != pic_AVOID) {
+        if (cmd_data->options.debug) {
+           printf("Adding: %s\n", DYNAMIC_LINK_OPTS);
+        }
+        push_count_chars(args, DYNAMIC_LINK_OPTS);
+        if (cmd_data->undefined_flag) {
+            push_count_chars(args, "-undefined");
+#if defined(__APPLE__)
+            /* -undefined dynamic_lookup is used by the bundled Python in
+             * 10.4, but if we don't set MACOSX_DEPLOYMENT_TARGET to 10.3+,
+             * we'll get a linker error if we pass this flag.
+             */
+            if (strcasecmp(cmd_data->undefined_flag,
+                           "dynamic_lookup") == 0) {
+                insert_count_chars(cmd_data->program_opts,
+                                   "MACOSX_DEPLOYMENT_TARGET=10.3", 0);
+            }
+#endif
+            push_count_chars(args, cmd_data->undefined_flag);
+        }
+        else {
+#ifdef DYNAMIC_LINK_UNDEFINED
+            if (cmd_data->options.debug) {
+                printf("Adding: %s\n", DYNAMIC_LINK_UNDEFINED);
+            }
+            push_count_chars(args, DYNAMIC_LINK_UNDEFINED);
+#endif
+        }
+    }
+#endif
+}
+
+/* Read the final install location and add it to runtime library search path. */
+#ifdef RPATH
+static void add_rpath(count_chars *cc, const char *path)
+{
+    int size = 0;
+    char *tmp;
+
+#ifdef LINKER_FLAG_PREFIX
+    size = strlen(LINKER_FLAG_PREFIX);
+#endif
+    size = size + strlen(path) + strlen(RPATH) + 2;
+    tmp = malloc(size);
+    if (tmp == NULL) {
+        return;
+    }
+#ifdef LINKER_FLAG_PREFIX
+    strcpy(tmp, LINKER_FLAG_PREFIX);
+    strcat(tmp, RPATH);
+#else
+    strcpy(tmp, RPATH);
+#endif
+#ifndef LINKER_FLAG_NO_EQUALS
+    strcat(tmp, "=");
+#endif
+    strcat(tmp, path);
+
+    push_count_chars(cc, tmp);
+}
+
+static void add_rpath_file(count_chars *cc, const char *arg)
+{
+    const char *path;
+
+    path = load_install_path(arg);
+    if (path) {
+        add_rpath(cc, path);
+    }
+}
+
+static void add_rpath_noinstall(count_chars *cc, const char *arg, int pathlen)
+{
+    const char *path;
+
+    path = load_noinstall_path(arg, pathlen);
+    if (path) {
+        add_rpath(cc, path);
+    }
+}
+#endif
+
+#ifdef DYNAMIC_LINK_NO_INSTALL
+static void add_dylink_noinstall(count_chars *cc, const char *arg, int pathlen,
+                          int extlen)
+{
+    const char *install_path, *current_path, *name;
+    char *exp_argument;
+    int i_p_len, c_p_len, name_len, dyext_len, cur_len;
+
+    install_path = load_install_path(arg);
+    current_path = load_noinstall_path(arg, pathlen);
+
+    if (!install_path || !current_path) {
+        return;
+    }
+
+    push_count_chars(cc, DYNAMIC_LINK_NO_INSTALL);
+
+    i_p_len = strlen(install_path);
+    c_p_len = strlen(current_path);
+
+    name = arg+pathlen;
+    name_len = extlen-pathlen;
+    dyext_len = sizeof(DYNAMIC_LIB_EXT) - 1;
+
+    /* No, we need to replace the extension. */
+    exp_argument = (char *)malloc(i_p_len + c_p_len + (name_len*2) +
+                                  (dyext_len*2) + 2);
+
+    cur_len = 0;
+    strcpy(exp_argument, install_path);
+    cur_len += i_p_len;
+    exp_argument[cur_len++] = '/';
+    strncpy(exp_argument+cur_len, name, extlen-pathlen);
+    cur_len += name_len;
+    strcpy(exp_argument+cur_len, DYNAMIC_LIB_EXT);
+    cur_len += dyext_len;
+    exp_argument[cur_len++] = ':';
+    strcpy(exp_argument+cur_len, current_path);
+    cur_len += c_p_len;
+    exp_argument[cur_len++] = '/';
+    strncpy(exp_argument+cur_len, name, extlen-pathlen);
+    cur_len += name_len;
+    strcpy(exp_argument+cur_len, DYNAMIC_LIB_EXT);
+    cur_len += dyext_len;
+
+    push_count_chars(cc, exp_argument);
+}
+#endif
+
+/* use -L -llibname to allow to use installed libraries */
+static void add_minus_l(count_chars *cc, const char *arg)
+{
+    char *newarg;
+    char *name = strrchr(arg, '/');
+    char *file = strrchr(arg, '.');
+    char *lib  = strstr(name, "lib");
+
+    if (name !=NULL && file != NULL && lib == name+1) {
+        *name = '\0';
+        *file = '\0';
+        file = name;
+        file = file+4;
+        push_count_chars(cc, "-L");
+        push_count_chars(cc, arg);
+        /* we need one argument like -lapr-1 */
+        newarg = malloc(strlen(file) + 3);
+        strcpy(newarg, "-l");
+        strcat(newarg, file);
+        push_count_chars(cc, newarg);
+    } else {
+        push_count_chars(cc, arg);
+    }
+}
+
+static void add_linker_flag_prefix(count_chars *cc, const char *arg)
+{
+#ifndef LINKER_FLAG_PREFIX
+    push_count_chars(cc, arg);
+#else
+    char *newarg;
+    newarg = (char*)malloc(strlen(arg) + sizeof(LINKER_FLAG_PREFIX) + 1);
+    strcpy(newarg, LINKER_FLAG_PREFIX);
+    strcat(newarg, arg);
+    push_count_chars(cc, newarg);
+#endif
+}
+
+static int explode_static_lib(command_t *cmd_data, const char *lib)
+{
+    count_chars tmpdir_cc, libname_cc;
+    const char *tmpdir, *libname;
+    char savewd[PATH_MAX];
+    const char *name;
+    DIR *dir;
+    struct dirent *entry;
+    const char *lib_args[4];
+
+    /* Bah! */
+    if (cmd_data->options.dry_run) {
+        return 0;
+    }
+
+    name = jlibtool_basename(lib);
+
+    init_count_chars(&tmpdir_cc);
+    push_count_chars(&tmpdir_cc, ".libs/");
+    push_count_chars(&tmpdir_cc, name);
+    push_count_chars(&tmpdir_cc, ".exploded/");
+    tmpdir = flatten_count_chars(&tmpdir_cc, 0);
+
+    if (!cmd_data->options.silent) {
+        printf("Making: %s\n", tmpdir);
+    }
+    safe_mkdir(tmpdir);
+
+    push_count_chars(cmd_data->tmp_dirs, tmpdir);
+
+    getcwd(savewd, sizeof(savewd));
+
+    if (chdir(tmpdir) != 0) {
+        if (!cmd_data->options.silent) {
+            printf("Warning: could not explode %s\n", lib);
+        }
+        return 1;
+    }
+
+    if (lib[0] == '/') {
+        libname = lib;
+    }
+    else {
+        init_count_chars(&libname_cc);
+        push_count_chars(&libname_cc, "../../");
+        push_count_chars(&libname_cc, lib);
+        libname = flatten_count_chars(&libname_cc, 0);
+    }
+
+    lib_args[0] = LIBRARIAN;
+    lib_args[1] = "x";
+    lib_args[2] = libname;
+    lib_args[3] = NULL;
+
+    external_spawn(cmd_data, LIBRARIAN, lib_args);
+
+    chdir(savewd);
+    dir = opendir(tmpdir);
+
+    while ((entry = readdir(dir)) != NULL) {
+#if defined(__APPLE__) && defined(RANLIB)
+        /* Apple inserts __.SYMDEF which isn't needed.
+         * Leopard (10.5+) can also add '__.SYMDEF SORTED' which isn't
+         * much fun either.  Just skip them.
+         */
+        if (strstr(entry->d_name, "__.SYMDEF") != NULL) {
+            continue;
+        }
+#endif
+        if (entry->d_name[0] != '.') {
+            push_count_chars(&tmpdir_cc, entry->d_name);
+            name = flatten_count_chars(&tmpdir_cc, 0);
+            if (cmd_data->options.debug) {
+                printf("Adding: %s\n", name);
+            }
+            push_count_chars(cmd_data->obj_files, name);
+            pop_count_chars(&tmpdir_cc);
+        }
+    }
+
+    closedir(dir);
+    return 0;
+}
+
+static int parse_input_file_name(char *arg, command_t *cmd_data)
+{
+    char *ext = strrchr(arg, '.');
+    const char *name;
+    int pathlen;
+    enum lib_type libtype;
+    char *newarg;
+
+    if (!ext) {
+        return 0;
+    }
+
+    ext++;
+    name = jlibtool_basename(arg);
+
+    pathlen = name - arg;
+
+    if (strcmp(ext, "lo") == 0) {
+        newarg = check_object_exists(cmd_data, arg, ext - arg);
+        if (!newarg) {
+            printf("Can not find suitable object file for %s\n", arg);
+            exit(1);
+        }
+        if (cmd_data->mode != mLink) {
+            push_count_chars(cmd_data->arglist, newarg);
+        }
+        else {
+            push_count_chars(cmd_data->obj_files, newarg);
+        }
+        return 1;
+    }
+
+    if (strcmp(ext, "la") == 0) {
+        switch (cmd_data->mode) {
+        case mLink:
+            /* Try the .libs dir first! */
+            newarg = check_library_exists(cmd_data, arg, pathlen, 1, &libtype);
+            if (!newarg) {
+                /* Try the normal dir next. */
+                newarg = check_library_exists(cmd_data, arg, pathlen, 0, &libtype);
+                if (!newarg) {
+                    printf("Can not find suitable library for %s\n", arg);
+                    exit(1);
+                }
+            }
+
+            /* It is not ok to just add the file: a library may added with:
+               1 - -L path library_name. (For *.so in Linux).
+               2 - library_name.
+             */
+#ifdef ADD_MINUS_L
+            if (libtype == type_DYNAMIC_LIB) {
+                 add_minus_l(cmd_data->shared_opts.dependencies, newarg);
+            } else if (cmd_data->output == otLibrary &&
+                       libtype == type_STATIC_LIB) {
+                explode_static_lib(cmd_data, newarg);
+            } else {
+                 push_count_chars(cmd_data->shared_opts.dependencies, newarg);
+            }
+#else
+            if (cmd_data->output == otLibrary && libtype == type_STATIC_LIB) {
+                explode_static_lib(cmd_data, newarg);
+            }
+            else {
+                push_count_chars(cmd_data->shared_opts.dependencies, newarg);
+            }
+#endif
+            if (libtype == type_DYNAMIC_LIB) {
+                if (cmd_data->options.no_install) {
+#ifdef RPATH
+                    add_rpath_noinstall(cmd_data->shared_opts.dependencies,
+                                        arg, pathlen);
+#endif
+#ifdef DYNAMIC_LINK_NO_INSTALL
+                    /*
+                     * This doesn't work as Darwin's linker has no way to
+                     * override at link-time the search paths for a
+                     * non-installed library.
+                     */
+                    /*
+                    add_dylink_noinstall(cmd_data->shared_opts.dependencies,
+                                         arg, pathlen, ext - arg);
+                    */
+#endif
+                }
+                else {
+#ifdef RPATH
+                    add_rpath_file(cmd_data->shared_opts.dependencies, arg);
+#endif
+                }
+            }
+            break;
+        case mInstall:
+            /* If we've already recorded a library to install, we're most
+             * likely getting the .la file that we want to install as.
+             * The problem is that we need to add it as the directory,
+             * not the .la file itself.  Otherwise, we'll do odd things.
+             */
+            if (cmd_data->output == otLibrary) {
+                arg[pathlen] = '\0';
+                push_count_chars(cmd_data->arglist, arg);
+            }
+            else {
+                cmd_data->output = otLibrary;
+                cmd_data->output_name = arg;
+                cmd_data->static_name.install = gen_install_name(arg, 0);
+                cmd_data->shared_name.install = gen_install_name(arg, 1);
+                cmd_data->module_name.install = gen_install_name(arg, 2);
+            }
+            break;
+        default:
+            break;
+        }
+        return 1;
+    }
+
+    if (strcmp(ext, "c") == 0) {
+        /* If we don't already have an idea what our output name will be. */
+        if (cmd_data->basename == NULL) {
+            cmd_data->basename = (char *)malloc(strlen(arg) + 4);
+            strcpy(cmd_data->basename, arg);
+            strcpy(strrchr(cmd_data->basename, '.') + 1, "lo");
+
+            cmd_data->fake_output_name = strrchr(cmd_data->basename, '/');
+            if (cmd_data->fake_output_name) {
+                cmd_data->fake_output_name++;
+            }
+            else {
+                cmd_data->fake_output_name = cmd_data->basename;
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int parse_output_file_name(char *arg, command_t *cmd_data)
+{
+    const char *name;
+    char *ext;
+    char *newarg = NULL;
+    int pathlen;
+
+    cmd_data->fake_output_name = arg;
+
+    name = jlibtool_basename(arg);
+    ext = strrchr(name, '.');
+    
+#ifdef EXE_EXT
+    if (!ext || strcmp(ext, EXE_EXT) == 0) {
+#else
+    if (!ext) {
+#endif
+        cmd_data->basename = arg;
+        cmd_data->output = otProgram;
+#if defined(_OSD_POSIX)
+        cmd_data->options.pic_mode = pic_AVOID;
+#endif
+        newarg = (char *)malloc(strlen(arg) + 5);
+        strcpy(newarg, arg);
+#ifdef EXE_EXT
+       if (!ext) {
+         strcat(newarg, EXE_EXT);
+       }
+#endif
+        cmd_data->output_name = newarg;
+        return 1;
+    }
+
+    ext++;
+    pathlen = name - arg;
+
+    if (strcmp(ext, "la") == 0) {
+        assert(cmd_data->mode == mLink);
+
+        cmd_data->basename = arg;
+        cmd_data->static_name.normal = gen_library_name(arg, 0);
+        cmd_data->shared_name.normal = gen_library_name(arg, 1);
+        cmd_data->module_name.normal = gen_library_name(arg, 2);
+        cmd_data->static_name.install = gen_install_name(arg, 0);
+        cmd_data->shared_name.install = gen_install_name(arg, 1);
+        cmd_data->module_name.install = gen_install_name(arg, 2);
+
+        if (!cmd_data->options.dry_run) {
+               char *cname;
+
+               cname = malloc(strlen(cmd_data->static_name.normal) + 1);
+               
+               strcpy(cname, cmd_data->static_name.normal);
+               ext = strrchr(cname, '/');
+               if (!ext) {
+                       /* Check first to see if the dir already exists! */
+                       safe_mkdir(".libs");
+               } else {
+                       *ext = '\0';
+                       safe_mkdir(cname);
+               }
+               free(cname);
+        }
+
+#ifdef TRUNCATE_DLL_NAME
+        if (shared) {
+          arg = truncate_dll_name(arg);
+        }
+#endif
+
+        cmd_data->output_name = arg;
+        return 1;
+    }
+
+    if (strcmp(ext, "lo") == 0) {
+        cmd_data->basename = arg;
+        cmd_data->output = otObject;
+        newarg = (char *)malloc(strlen(arg) + 2);
+        strcpy(newarg, arg);
+        ext = strrchr(newarg, '.') + 1;
+        strcpy(ext, OBJECT_EXT);
+        cmd_data->output_name = newarg;
+        return 1;
+    }
+
+    return 0;
+}
+
+static void parse_args(int argc, char *argv[], command_t *cmd_data)
+{
+    int a;
+    char *arg;
+    int argused;
+
+    for (a = 1; a < argc; a++) {
+        arg = argv[a];
+        argused = 1;
+
+        if (arg[0] == '-') {
+            if (arg[1] == '-') {
+                argused = parse_long_opt(arg + 2, cmd_data);
+            }
+            else {
+                argused = parse_short_opt(arg + 1, cmd_data);
+            }
+
+            /* We haven't done anything with it yet, try some of the
+             * more complicated short opts... */
+            if (argused == 0 && a + 1 < argc) {
+                if (arg[1] == 'o' && !arg[2]) {
+                    arg = argv[++a];
+                    argused = parse_output_file_name(arg, cmd_data);
+                } else if (strcmp(arg+1, "MT") == 0) {
+                    if (cmd_data->options.debug) {
+                        printf("Adding: %s\n", arg);
+                    }
+                    push_count_chars(cmd_data->arglist, arg);
+                    arg = argv[++a];
+                    if (!cmd_data->options.silent) {
+                        printf(" %s\n", arg);
+                    }
+                    push_count_chars(cmd_data->arglist, arg);
+                    argused = 1;
+                } else if (strcmp(arg+1, "rpath") == 0) {
+                    /* Aha, we should try to link both! */
+                    cmd_data->install_path = argv[++a];
+                    argused = 1;
+                } else if (strcmp(arg+1, "release") == 0) {
+                    /* Store for later deciphering */
+                    cmd_data->version_info = argv[++a];
+                    argused = 1;
+                } else if (strcmp(arg+1, "version-info") == 0) {
+                    /* Store for later deciphering */
+                    cmd_data->version_info = argv[++a];
+                    argused = 1;
+                } else if (strcmp(arg+1, "export-symbols-regex") == 0) {
+                    /* Skip the argument. */
+                    ++a;
+                    argused = 1;
+                } else if (strcmp(arg+1, "release") == 0) {
+                    /* Skip the argument. */
+                    ++a;
+                    argused = 1;
+                } else if (strcmp(arg+1, "undefined") == 0) {
+                    cmd_data->undefined_flag = argv[++a];
+                    argused = 1;
+                } else if (arg[1] == 'R' && !arg[2]) {
+                    /* -R dir Add dir to runtime library search path. */
+                    add_runtimedirlib(argv[++a], cmd_data);
+                    argused = 1;
+                }
+            }
+        } else {
+            argused = parse_input_file_name(arg, cmd_data);
+        }
+
+        if (!argused) {
+            if (cmd_data->options.debug) {
+                printf("Adding: %s\n", arg);
+            }
+            push_count_chars(cmd_data->arglist, arg);
+        }
+    }
+
+}
+
+#ifdef GEN_EXPORTS
+static void generate_def_file(command_t *cmd_data)
+{
+    char def_file[1024];
+    char implib_file[1024];
+    char *ext;
+    FILE *hDef;
+    char *export_args[1024];
+    int num_export_args = 0;
+    char *cmd;
+    int cmd_size = 0;
+    int a;
+
+    if (cmd_data->output_name) {
+        strcpy(def_file, cmd_data->output_name);
+        strcat(def_file, ".def");
+        hDef = fopen(def_file, "w");
+
+        if (hDef != NULL) {
+            fprintf(hDef, "LIBRARY '%s' INITINSTANCE\n", nameof(cmd_data->output_name));
+            fprintf(hDef, "DATA NONSHARED\n");
+            fprintf(hDef, "EXPORTS\n");
+            fclose(hDef);
+
+            for (a = 0; a < cmd_data->num_obj_files; a++) {
+                cmd_size += strlen(cmd_data->obj_files[a]) + 1;
+            }
+
+            cmd_size += strlen(GEN_EXPORTS) + strlen(def_file) + 3;
+            cmd = (char *)malloc(cmd_size);
+            strcpy(cmd, GEN_EXPORTS);
+
+            for (a=0; a < cmd_data->num_obj_files; a++) {
+                strcat(cmd, " ");
+                strcat(cmd, cmd_data->obj_files[a] );
+            }
+
+            strcat(cmd, ">>");
+            strcat(cmd, def_file);
+            puts(cmd);
+            export_args[num_export_args++] = SHELL_CMD;
+            export_args[num_export_args++] = "-c";
+            export_args[num_export_args++] = cmd;
+            export_args[num_export_args++] = NULL;
+            external_spawn(cmd_data, export_args[0], (const char**)export_args);
+            cmd_data->arglist[cmd_data->num_args++] = strdup(def_file);
+
+            /* Now make an import library for the dll */
+            num_export_args = 0;
+            export_args[num_export_args++] = DEF2IMPLIB_CMD;
+            export_args[num_export_args++] = "-o";
+
+            strcpy(implib_file, ".libs/");
+            strcat(implib_file, cmd_data->basename);
+            ext = strrchr(implib_file, '.');
+
+            if (ext)
+                *ext = 0;
+
+            strcat(implib_file, ".");
+            strcat(implib_file, STATIC_LIB_EXT);
+
+            export_args[num_export_args++] = implib_file;
+            export_args[num_export_args++] = def_file;
+            export_args[num_export_args++] = NULL;
+            external_spawn(cmd_data, export_args[0], (const char**)export_args);
+
+        }
+    }
+}
+#endif
+
+static const char* expand_path(const char *relpath)
+{
+    char foo[PATH_MAX], *newpath;
+
+    getcwd(foo, PATH_MAX-1);
+    newpath = (char*)malloc(strlen(foo)+strlen(relpath)+2);
+    strcat(newpath, foo);
+    strcat(newpath, "/");
+    strcat(newpath, relpath);
+    return newpath;
+}
+
+static void link_fixup(command_t *c)
+{
+    /* If we were passed an -rpath directive, we need to build
+     * shared objects too.  Otherwise, we should only create static
+     * libraries.
+     */
+    if (!c->install_path && (c->output == otDynamicLibraryOnly ||
+        c->output == otModule || c->output == otLibrary)) {
+        c->output = otStaticLibraryOnly;
+    }
+
+    if (c->output == otDynamicLibraryOnly ||
+        c->output == otModule ||
+        c->output == otLibrary) {
+
+        push_count_chars(c->shared_opts.normal, "-o");
+        if (c->output == otModule) {
+            push_count_chars(c->shared_opts.normal, c->module_name.normal);
+        }
+        else {
+            char *tmp;
+            push_count_chars(c->shared_opts.normal, c->shared_name.normal);
+#ifdef DYNAMIC_INSTALL_NAME
+            push_count_chars(c->shared_opts.normal, DYNAMIC_INSTALL_NAME);
+
+            tmp = (char*)malloc(PATH_MAX);
+            strcat(tmp, c->install_path);
+            strcat(tmp, strrchr(c->shared_name.normal, '/'));
+            push_count_chars(c->shared_opts.normal, tmp);
+#endif
+        }
+
+        append_count_chars(c->shared_opts.normal, c->obj_files);
+        append_count_chars(c->shared_opts.normal, c->shared_opts.dependencies);
+
+        if (c->options.export_all) {
+#ifdef GEN_EXPORTS
+            generate_def_file(c);
+#endif
+        }
+    }
+
+    if (c->output == otLibrary || c->output == otStaticLibraryOnly) {
+        push_count_chars(c->static_opts.normal, "-o");
+        push_count_chars(c->static_opts.normal, c->output_name);
+    }
+
+    if (c->output == otProgram) {
+        if (c->output_name) {
+            push_count_chars(c->arglist, "-o");
+            push_count_chars(c->arglist, c->output_name);
+            append_count_chars(c->arglist, c->obj_files);
+            append_count_chars(c->arglist, c->shared_opts.dependencies);
+            add_dynamic_link_opts(c, c->arglist);
+        }
+    }
+}
+
+static void post_parse_fixup(command_t *cmd_data)
+{
+    switch (cmd_data->mode)
+    {
+    case mCompile:
+#ifdef PIC_FLAG
+        if (cmd_data->options.pic_mode != pic_AVOID) {
+            push_count_chars(cmd_data->arglist, PIC_FLAG);
+        }
+#endif
+        if (cmd_data->output_name) {
+            push_count_chars(cmd_data->arglist, "-o");
+            push_count_chars(cmd_data->arglist, cmd_data->output_name);
+        }
+        break;
+    case mLink:
+        link_fixup(cmd_data);
+        break;
+    case mInstall:
+        if (cmd_data->output == otLibrary) {
+            link_fixup(cmd_data);
+        }
+    default:
+        break;
+    }
+
+#if USE_OMF
+    if (cmd_data->output == otObject ||
+        cmd_data->output == otProgram ||
+        cmd_data->output == otLibrary ||
+        cmd_data->output == otDynamicLibraryOnly) {
+        push_count_chars(cmd_data->arglist, "-Zomf");
+    }
+#endif
+
+    if (cmd_data->options.shared &&
+            (cmd_data->output == otObject ||
+             cmd_data->output == otLibrary ||
+             cmd_data->output == otDynamicLibraryOnly)) {
+#ifdef SHARE_SW
+        push_count_chars(cmd_data->arglist, SHARE_SW);
+#endif
+    }
+}
+
+static int run_mode(command_t *cmd_data)
+{
+    int rv;
+    count_chars *cctemp;
+
+    cctemp = (count_chars*)malloc(sizeof(count_chars));
+    init_count_chars(cctemp);
+
+    switch (cmd_data->mode)
+    {
+    case mCompile:
+        rv = run_command(cmd_data, cmd_data->arglist);
+        if (rv) {
+            return rv;
+        }
+        break;
+    case mInstall:
+        /* Well, we'll assume it's a file going to a directory... */
+        /* For brain-dead install-sh based scripts, we have to repeat
+         * the command N-times.  install-sh should die.
+         */
+        if (!cmd_data->output_name) {
+            rv = run_command(cmd_data, cmd_data->arglist);
+            if (rv) {
+                return rv;
+            }
+        }
+        if (cmd_data->output_name) {
+            append_count_chars(cctemp, cmd_data->arglist);
+            insert_count_chars(cctemp,
+                               cmd_data->output_name,
+                               cctemp->num - 1);
+            rv = run_command(cmd_data, cctemp);
+            if (rv) {
+                return rv;
+            }
+            clear_count_chars(cctemp);
+        }
+        if (cmd_data->static_name.install) {
+            append_count_chars(cctemp, cmd_data->arglist);
+            insert_count_chars(cctemp,
+                               cmd_data->static_name.install,
+                               cctemp->num - 1);
+            rv = run_command(cmd_data, cctemp);
+            if (rv) {
+                return rv;
+            }
+#if defined(__APPLE__) && defined(RANLIB)
+            /* From the Apple libtool(1) manpage on Tiger/10.4:
+             * ----
+             * With  the way libraries used to be created, errors were possible
+             * if the library was modified with ar(1) and  the  table  of
+             * contents  was  not updated  by  rerunning ranlib(1).  Thus the
+             * link editor, ld, warns when the modification date of a library
+             * is more  recent  than  the  creation date  of its table of
+             * contents.  Unfortunately, this means that you get the warning
+             * even if you only copy the library.
+             * ----
+             *
+             * This means that when we install the static archive, we need to
+             * rerun ranlib afterwards.
+             */
+            const char *lib_args[3], *static_lib_name;
+            char *tmp;
+            size_t len1, len2;
+            len1 = strlen(cmd_data->arglist->vals[cmd_data->arglist->num - 1]);
+
+            static_lib_name = jlibtool_basename(cmd_data->static_name.install);
+            len2 = strlen(static_lib_name);
+
+            tmp = malloc(len1 + len2 + 2);
+
+            snprintf(tmp, len1 + len2 + 2, "%s/%s",
+                    cmd_data->arglist->vals[cmd_data->arglist->num - 1],
+                    static_lib_name);
+
+            lib_args[0] = RANLIB;
+            lib_args[1] = tmp;
+            lib_args[2] = NULL;
+            external_spawn(cmd_data, RANLIB, lib_args);
+            free(tmp);
+#endif
+            clear_count_chars(cctemp);
+        }
+        if (cmd_data->shared_name.install) {
+            append_count_chars(cctemp, cmd_data->arglist);
+            insert_count_chars(cctemp,
+                               cmd_data->shared_name.install,
+                               cctemp->num - 1);
+            rv = run_command(cmd_data, cctemp);
+            if (rv) {
+                return rv;
+            }
+            clear_count_chars(cctemp);
+        }
+        if (cmd_data->module_name.install) {
+            append_count_chars(cctemp, cmd_data->arglist);
+            insert_count_chars(cctemp,
+                               cmd_data->module_name.install,
+                               cctemp->num - 1);
+            rv = run_command(cmd_data, cctemp);
+            if (rv) {
+                return rv;
+            }
+            clear_count_chars(cctemp);
+        }
+        break;
+    case mLink:
+        if (cmd_data->output == otStaticLibraryOnly ||
+            cmd_data->output == otLibrary) {
+#ifdef RANLIB
+            const char *lib_args[3];
+#endif
+            /* Removes compiler! */
+            cmd_data->program = LIBRARIAN;
+            push_count_chars(cmd_data->program_opts, LIBRARIAN_OPTS);
+            push_count_chars(cmd_data->program_opts,
+                             cmd_data->static_name.normal);
+
+            rv = run_command(cmd_data, cmd_data->obj_files);
+            if (rv) {
+                return rv;
+            }
+
+#ifdef RANLIB
+            lib_args[0] = RANLIB;
+            lib_args[1] = cmd_data->static_name.normal;
+            lib_args[2] = NULL;
+            external_spawn(cmd_data, RANLIB, lib_args);
+#endif
+        }
+
+        if (cmd_data->output == otDynamicLibraryOnly ||
+            cmd_data->output == otModule ||
+            cmd_data->output == otLibrary) {
+            cmd_data->program = NULL;
+            clear_count_chars(cmd_data->program_opts);
+
+            append_count_chars(cmd_data->program_opts, cmd_data->arglist);
+            if (cmd_data->output == otModule) {
+#ifdef MODULE_OPTS
+                push_count_chars(cmd_data->program_opts, MODULE_OPTS);
+#endif
+            } else {
+#ifdef SHARED_OPTS
+                push_count_chars(cmd_data->program_opts, SHARED_OPTS);
+#endif
+#ifdef dynamic_link_version_func
+                push_count_chars(cmd_data->program_opts,
+                             dynamic_link_version_func(cmd_data->version_info));
+#endif
+            }
+            add_dynamic_link_opts(cmd_data, cmd_data->program_opts);
+
+            rv = run_command(cmd_data, cmd_data->shared_opts.normal);
+            if (rv) {
+                return rv;
+            }
+        }
+        if (cmd_data->output == otProgram) {
+            rv = run_command(cmd_data, cmd_data->arglist);
+            if (rv) {
+                return rv;
+            }
+        }
+        break;
+    case mExecute:
+    {
+        char *l, libpath[PATH_MAX];
+      
+        strcpy(libpath, cmd_data->arglist->vals[0]);
+        add_dotlibs(libpath);
+       l = strrchr(libpath, '/');
+       if (!l) l = strrchr(libpath, '\\');
+       if (l) {
+           *l = '\0';
+           l = libpath;
+       } else {
+           l = ".libs/";
+       }
+      
+       setenv(LD_LIBRARY_PATH_LOCAL, "./build/lib/.libs/", 1);
+       rv = run_command(cmd_data, cmd_data->arglist);
+       if (rv) {
+           return rv;
+       }
+    }
+      break;
+
+    default:
+        break;
+    } 
+
+    return 0;
+}
+
+static void cleanup_tmp_dir(const char *dirname)
+{
+    DIR *dir;
+    struct dirent *entry;
+    char fullname[1024];
+
+    dir = opendir(dirname);
+
+    if (dir == NULL)
+        return;
+
+    while ((entry = readdir(dir)) != NULL) {
+        if (entry->d_name[0] != '.') {
+            strcpy(fullname, dirname);
+            strcat(fullname, "/");
+            strcat(fullname, entry->d_name);
+            remove(fullname);
+        }
+    }
+
+    rmdir(dirname);
+}
+
+static void cleanup_tmp_dirs(command_t *cmd_data)
+{
+    int d;
+
+    for (d = 0; d < cmd_data->tmp_dirs->num; d++) {
+        cleanup_tmp_dir(cmd_data->tmp_dirs->vals[d]);
+    }
+}
+
+static int ensure_fake_uptodate(command_t *cmd_data)
+{
+    /* FIXME: could do the stat/touch here, but nah... */
+    const char *touch_args[3];
+
+    if (cmd_data->mode == mInstall) {
+        return 0;
+    }
+    if (!cmd_data->fake_output_name) {
+        return 0;
+    }
+
+    touch_args[0] = "touch";
+    touch_args[1] = cmd_data->fake_output_name;
+    touch_args[2] = NULL;
+    return external_spawn(cmd_data, "touch", touch_args);
+}
+
+/* Store the install path in the *.la file */
+static int add_for_runtime(command_t *cmd_data)
+{
+    if (cmd_data->mode == mInstall) {
+        return 0;
+    }
+    if (cmd_data->output == otDynamicLibraryOnly ||
+        cmd_data->output == otLibrary) {
+        FILE *f=fopen(cmd_data->fake_output_name,"w");
+        if (f == NULL) {
+            return -1;
+        }
+        fprintf(f,"%s\n", cmd_data->install_path);
+        fclose(f);
+        return(0);
+    } else {
+        return(ensure_fake_uptodate(cmd_data));
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    int rc;
+    command_t cmd_data;
+
+    memset(&cmd_data, 0, sizeof(cmd_data));
+
+    cmd_data.options.pic_mode = pic_UNKNOWN;
+
+    cmd_data.program_opts = (count_chars*)malloc(sizeof(count_chars));
+    init_count_chars(cmd_data.program_opts);
+    cmd_data.arglist = (count_chars*)malloc(sizeof(count_chars));
+    init_count_chars(cmd_data.arglist);
+    cmd_data.tmp_dirs = (count_chars*)malloc(sizeof(count_chars));
+    init_count_chars(cmd_data.tmp_dirs);
+    cmd_data.obj_files = (count_chars*)malloc(sizeof(count_chars));
+    init_count_chars(cmd_data.obj_files);
+    cmd_data.dep_rpaths = (count_chars*)malloc(sizeof(count_chars));
+    init_count_chars(cmd_data.dep_rpaths);
+    cmd_data.rpaths = (count_chars*)malloc(sizeof(count_chars));
+    init_count_chars(cmd_data.rpaths);
+    cmd_data.static_opts.normal = (count_chars*)malloc(sizeof(count_chars));
+    init_count_chars(cmd_data.static_opts.normal);
+    cmd_data.shared_opts.normal = (count_chars*)malloc(sizeof(count_chars));
+    init_count_chars(cmd_data.shared_opts.normal);
+    cmd_data.shared_opts.dependencies = (count_chars*)malloc(sizeof(count_chars));
+    init_count_chars(cmd_data.shared_opts.dependencies);
+
+    cmd_data.mode = mUnknown;
+    cmd_data.output = otGeneral;
+
+    parse_args(argc, argv, &cmd_data);
+    post_parse_fixup(&cmd_data);
+
+    if (cmd_data.mode == mUnknown) {
+       usage(1);
+    }
+
+    rc = run_mode(&cmd_data);
+
+    if (!rc) {
+       add_for_runtime(&cmd_data); 
+    }
+
+    cleanup_tmp_dirs(&cmd_data);
+    return rc;
+}
diff --git a/scripts/libtool.mk b/scripts/libtool.mk
new file mode 100644 (file)
index 0000000..4238325
--- /dev/null
@@ -0,0 +1,212 @@
+# Copyright 2008, 2009, 2010 Dan Moulding, Alan T. DeKok
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Add these rules only when LIBTOOL is being used.
+ifneq "${LIBTOOL}" ""
+
+# JLIBTOOL - check if we're using the local (fast) jlibtool, rather
+#   than the GNU (slow) libtool shell script.  If so, add rules
+#   to build it.
+
+ifeq "${LIBTOOL}" "JLIBTOOL"
+    JLIBTOOL := ${BUILD_DIR}/make/jlibtool
+
+    # Add a rule to build jlibtool BEFORE any other targets.  This
+    # means that we can use it to build the later targets.
+    all install: ${JLIBTOOL}
+
+    # Note that we need to use a compilation rule that does NOT
+    # include referencing ${LIBTOOL}, as we don't have a jlibtool
+    # binary!
+    jlibtool ${JLIBTOOL}: ${top_makedir}/jlibtool.c
+       @mkdir -p $(dir ${JLIBTOOL})
+       ${CC} $< -o ${JLIBTOOL}
+
+    clean: jlibtool_clean
+
+    .PHONY: jlibtool_clean
+    jlibtool_clean:
+       @rm -f ${JLIBTOOL}
+
+    # Tell GNU Make to use this value, rather than anything specified
+    # on the command line.
+    override LIBTOOL := ${JLIBTOOL}
+endif    # else we're not using jlibtool
+
+# When using libtool, it produces a '.libs' directory.  Ensure that it
+# is removed on "make clean", too.
+#
+clean: .libs_clean
+
+.PHONY: .libs_clean
+.libs_clean:
+       @rm -rf ${BUILD_DIR}/.libs/
+
+# Re-define compilers and linkers
+#
+OBJ_EXT = lo
+COMPILE.c = ${LIBTOOL} --silent --mode=compile ${CC}
+COMPILE.cxx = ${LIBTOOL} --mode=compile ${CXX}
+LINK.c = ${LIBTOOL} --silent --mode=link ${CC}
+LINK.cxx = ${LIBTOOL} --mode=link ${CXX}
+PROGRAM_INSTALL = ${LIBTOOL} --silent --mode=install ${INSTALL}
+
+
+# LIBTOOL_ENDINGS - Given a library ending in ".a" or ".so", replace that
+#   extension with ".la".
+#
+define LIBTOOL_ENDINGS
+$(patsubst %.a,%.la,$(patsubst %.so,%.la,${1}))
+endef
+
+# ADD_TARGET_RULE.la - Build a ".la" target.
+#
+#   USE WITH EVAL
+#
+define ADD_TARGET_RULE.la
+    # So "make ${1}" works
+    .PHONY: ${1}
+    ${1}: $${${1}_BUILD}/${1}
+
+    # Create libtool library ${1}
+    $${${1}_BUILD}/${1}: $${${1}_OBJS} $${${1}_PREREQS}
+           @$(strip mkdir -p $(dir $${${1}_BUILD}/${1}))
+           @$(ECHO) LINK $${${1}_BUILD}/${1}
+           @$${${1}_LINKER} -o $${${1}_BUILD}/${1} $${RPATH_FLAGS} $${LDFLAGS} \
+                $${${1}_LDFLAGS} $${${1}_OBJS} $${LDLIBS} $${${1}_LDLIBS}
+           @$${${1}_POSTMAKE}
+
+endef
+
+# ADD_RELINK_RULE.exe - Parametric "function" that adds a rule to relink
+#   the target before installation, so that the paths are correct.
+#
+#   USE WITH EVAL
+#
+define ADD_RELINK_RULE.exe
+    ${1}: $${${1}_BUILD}/$${${1}_RELINK}
+
+    # used to fix up RPATH for ${1} on install.
+    $${${1}_BUILD}/$${${1}_RELINK}: $${${1}_OBJS} $${${1}_PRBIN} $${${1}_R_PRLIBS}
+           @$(strip mkdir -p $${${1}_BUILD}/${RELINK}/)
+           @$${${1}_LINKER} -o $${${1}_BUILD}/$${${1}_RELINK} $${RELINK_FLAGS} $${LDFLAGS} \
+                $${${1}_LDFLAGS} $${${1}_OBJS} $${${1}_R_PRLIBS} \
+                $${LDLIBS} $${${1}_LDLIBS}
+           @$${${1}_POSTMAKE}
+endef
+
+# ADD_RELINK_RULE.la - Parametric "function" that adds a rule to relink
+#   the target before installation, so that the paths are correct.
+#
+#   USE WITH EVAL
+#
+define ADD_RELINK_RULE.la
+    ${1}: $${${1}_BUILD}/$${${1}_RELINK}
+
+    # used to fix up RPATH for ${1} on install.
+    $${${1}_BUILD}/$${${1}_RELINK}: $${${1}_OBJS} $${${1}_PREREQS}
+           @$(strip mkdir -p $${${1}_BUILD}/${RELINK}/)
+           @$${${1}_LINKER} -o $${${1}_BUILD}/$${${1}_RELINK} $${RELINK_FLAGS} $${LDFLAGS} \
+                $${${1}_LDFLAGS} $${${1}_OBJS} $${LDLIBS} $${${1}_LDLIBS}
+           @$${${1}_POSTMAKE}
+
+endef
+
+# By default, if libdir is defined, we build shared libraries.
+# However, we can disable shared libraries if explicitly told to.
+ifneq "${libdir}" ""
+    ifneq "bm_shared_libs" "no"
+        bm_shared_libs := yes
+    endif
+endif
+
+# Default to building static libraries, too.
+ifneq "${bm_static_libs}" "no"
+    bm_static_libs := yes
+endif
+
+# Check if we build shared libraries.
+ifeq "${bm_shared_libs}" "yes"
+    # RPATH  : flags use to build executables that can be run
+    #          from the build directory / source tree.
+    # RELINK : flags use to build executables that are installed,
+    #          with no dependency on the source. 
+    RPATH_FLAGS := -rpath $(abspath ${BUILD_DIR})/lib/.libs -rdynamic
+    RELINK_FLAGS := -rpath ${libdir} -rdynamic
+    RELINK := relink/
+
+    ifneq "${bm_static_libs}" "yes"
+        RPATH_FLAGS += --shared
+        RELINK_FLAGS += --shared
+    endif
+else
+    ifneq "${bm_static_libs}" "yes"
+        $(error Building without static libraries requires you to set 'INSTALL' or 'libdir')
+    endif
+
+    RPATH_FLAGS := -static
+endif
+
+# UPDATE_TARGET_ENDINGS - Function to turn target into a libtool target
+#   e.g. "libfoo.a" -> libfoo.la"
+#
+#   If the target is an executable, then its extension doesn't change
+#   when we use libtool, and we don't do any re-writing.
+#
+#   USE WITH EVAL
+#
+define ADD_LIBTOOL_SUFFIX
+    ifneq "$$(call LIBTOOL_ENDINGS,$${TGT})" "$${TGT}"
+        TGT_NOLIBTOOL := $${TGT}
+        TGT := $$(call LIBTOOL_ENDINGS,$${TGT})
+        $${TGT}_NOLIBTOOL := $${TGT_NOLIBTOOL}
+    endif
+
+    ifneq "$${RELINK_FLAGS}" ""
+        $${TGT}_RELINK := ${RELINK}$${TGT}
+    endif
+
+    # re-write all of the dependencies to have the libtool endings.
+    TGT_PREREQS := $$(call LIBTOOL_ENDINGS,$${TGT_PREREQS})
+endef
+
+# ADD_LIBTOOL_TARGET - Function to ensure that the object files depend
+#   on our jlibtool target.  This ensures that jlibtool is built before
+#   it's used to build the object files.
+#
+#   USE WITH EVAL
+#
+define ADD_LIBTOOL_TARGET
+    ifneq "${JLIBTOOL}" ""
+        $${$${TGT}_OBJS}: $${JLIBTOOL}
+    endif
+
+    ifneq "$${$${TGT}_NOLIBTOOL}" ""
+        $$(notdir $${$${TGT}_NOLIBTOOL}): $${TGT}
+    endif
+
+    # If we need to relink, add the relink targets now.
+    ifneq "$${$${TGT}_RELINK}" ""
+        # add rules to relink the target
+
+        $${TGT}_R_PRLIBS := $$(subst /lib/,/lib/relink/,$${$${TGT}_PRLIBS})
+
+        $$(eval $$(call ADD_RELINK_RULE$${$${TGT}_SUFFIX},$${TGT}))
+    endif
+
+endef
+
+
+endif
diff --git a/scripts/main.mk b/scripts/main.mk
new file mode 100644 (file)
index 0000000..4184970
--- /dev/null
@@ -0,0 +1,44 @@
+# We don't use boilermake here because we want to run the test-app
+# as a self-contained system that runs boilermake.
+#
+
+all: run-tests
+
+APP := ./test-app/build/bin/talk
+
+.PHONY: run-tests
+run-tests:
+       ${MAKE} clean
+       ${MAKE} -C test-app/
+       ${APP} > found.txt
+       diff expected.txt found.txt
+       ${MAKE} -C test-app/ DESTDIR=`pwd`/R INSTALL=`pwd`/install-sh install
+       find R/* -print > found-install.txt
+       diff expected-install.txt found-install.txt
+       ${APP} > found.txt
+       diff expected.txt found.txt
+       ${MAKE} -C test-app/ DESTDIR=`pwd`/R INSTALL=`pwd`/install-sh uninstall
+       find R/* -print > found-install.txt
+       diff empty-install.txt found-install.txt
+       ${MAKE} clean
+       ${MAKE} -C test-app/ LIBTOOL=JLIBTOOL DESTDIR=`pwd`/R INSTALL=`pwd`/install-sh all
+       ${APP} > found.txt
+       diff expected.txt found.txt
+       ${MAKE} -C test-app/ LIBTOOL=JLIBTOOL DESTDIR=`pwd`/R INSTALL=`pwd`/install-sh install
+# don't do "find", as we have *.la files installed, rather than *.a
+       ${APP} > found.txt
+       diff expected.txt found.txt
+       ${MAKE} clean
+       rm -rf R found found-install.txt
+
+clean: clean.local
+
+clean.local:
+       ${MAKE} -C test-app/ clean
+       ${MAKE} -C test-app/ LIBTOOL=x clean
+       rm -rf ./R *~ found.txt found-install.txt
+
+check-legacy:
+       @grep '$$(' `find test-app/build/make -type f -name "*\.mk" -print` || true
+       @grep ' /' `find test-app/build/make -type f -name "*\.mk" -print` || true
+       @grep ' build' `find test-app/build/make -type f -name "*\.mk" -print` || true
index a7677a4..a2e3592 100644 (file)
@@ -85,6 +85,7 @@ $INCLUDE dictionary.rfc4679
 $INCLUDE dictionary.rfc4818
 $INCLUDE dictionary.rfc4849
 $INCLUDE dictionary.rfc5176
+$INCLUDE dictionary.rfc5447
 $INCLUDE dictionary.rfc5580
 $INCLUDE dictionary.rfc5607
 $INCLUDE dictionary.rfc5904
index 0842a6c..ff8223b 100644 (file)
@@ -14,6 +14,11 @@ ATTRIBUTE    Manzara-Full-Login-String               6       string
 ATTRIBUTE      Manzara-Tariff-Units                    7       integer
 ATTRIBUTE      Manzara-Tariff-Type                     8       integer
 ATTRIBUTE      Manzara-ECP-Session-Key                 9       octets
+ATTRIBUTE      Manzara-Map-Name                        10      string
+ATTRIBUTE      Manzara-Map-Key                         11      string
+ATTRIBUTE      Manzara-Map-Value                       12      string
+ATTRIBUTE      Manzara-Map-Error                       13      string
+ATTRIBUTE      Manzara-Service-Type                    14      string
 
 VALUE  Manzara-Tariff-Type             MMS-Picture             1
 VALUE  Manzara-Tariff-Type             Unused                  2
diff --git a/share/dictionary.rfc5447 b/share/dictionary.rfc5447
new file mode 100644 (file)
index 0000000..7f5b708
--- /dev/null
@@ -0,0 +1,12 @@
+# -*- text -*-
+# Copyright (C) 2012 The FreeRADIUS Server project and contributors
+#
+#      Attributes and values defined in RFC 5447.
+#      http://www.ietf.org/rfc/rfc5447.txt
+#
+#      $Id$
+#
+
+# 64-bit bit field
+ATTRIBUTE      MIP6-Feature-Vector                     124     octets
+ATTRIBUTE      MIP6-Home-Link-Prefix                   125     ipv6prefix
index a79ce07..badca55 100644 (file)
@@ -45,4 +45,4 @@ $(SUBDIRS):
        @$(MAKE) $(MFLAGS) X=$(X)src/ -C $@ $(WHAT_TO_MAKE)
 
 freeradius-devel:
-       ln -s include freeradius-devel
+       ln -sf include freeradius-devel
diff --git a/src/all.mk b/src/all.mk
new file mode 100644 (file)
index 0000000..25f8239
--- /dev/null
@@ -0,0 +1,14 @@
+# add this dependency BEFORE including the other submakefiles.
+all: ${BUILD_DIR}/make/include/freeradius-devel src/freeradius-devel
+
+#TARGET        := src/freeradius-devel
+
+# Ensure that the devel files have access to radpaths.h
+${BUILD_DIR}/make/include/freeradius-devel: src/include/radpaths.h
+       @[ -e $@ ] || (mkdir -p $(dir $@) && ln -s ${top_builddir}/src/include $@)
+
+src/freeradius-devel: src/include/radpaths.h
+       @[ -e $@ ] || ln -s include $@
+
+SUBMAKEFILES := include/all.mk lib/all.mk modules/all.mk main/all.mk
+
diff --git a/src/include/all.mk b/src/include/all.mk
new file mode 100644 (file)
index 0000000..c645d40
--- /dev/null
@@ -0,0 +1,40 @@
+#
+# Makefile
+#
+# Version:     $Id$
+#
+
+HEADERS        = autoconf.h conf.h conffile.h detail.h dhcp.h event.h hash.h heap.h \
+       ident.h libradius.h md4.h md5.h missing.h modcall.h modules.h \
+       packet.h rad_assert.h radius.h radiusd.h radpaths.h \
+       radutmp.h realms.h sha1.h stats.h sysutmp.h token.h \
+       udpfromto.h vmps.h vqp.h
+
+# Our target
+TARGET := src/include/radpaths.h
+
+src/include/radpaths.h: src/include/build-radpaths-h
+       cd src/include && /bin/sh build-radpaths-h
+
+# global install depends on the local rule
+install: install.src.include
+
+# define the installation directory
+SRC_INCLUDE_DIR := ${R}${includedir}/freeradius
+
+# the local rule depends on the installed headers
+install.src.include: $(addprefix ${SRC_INCLUDE_DIR}/,${HEADERS})
+
+# the installed headers require a directory
+$(addprefix ${SRC_INCLUDE_DIR}/,${HEADERS}): ${SRC_INCLUDE_DIR}/
+
+# make the directory
+.PHONY: 
+${SRC_INCLUDE_DIR}/:
+       $(INSTALL) -d -m 755 $@
+
+# install the headers by re-writing the local files
+${SRC_INCLUDE_DIR}/%.h: ${top_srcdir}/src/include/%.h
+       @echo INSTALL $(notdir $<)
+       @sed 's/^#include <freeradius-devel/#include <freeradius/' < $< > $@
+       @chmod 644 $@
index b3fa8da..4b5618b 100644 (file)
@@ -231,7 +231,6 @@ typedef struct radius_packet {
        uint16_t                dst_port;
        int                     id;
        unsigned int            code;
-       uint32_t                hash;
        uint8_t                 vector[AUTH_VECTOR_LEN];
        struct timeval          timestamp;
        uint8_t                 *data;
@@ -274,6 +273,7 @@ DICT_ATTR   *dict_attrbyvalue(unsigned int attr, unsigned int vendor);
 DICT_ATTR      *dict_attrbyname(const char *attr);
 DICT_VALUE     *dict_valbyattr(unsigned int attr, unsigned int vendor, int val);
 DICT_VALUE     *dict_valbyname(unsigned int attr, unsigned int vendor, const char *val);
+const char     *dict_valnamebyattr(unsigned int attr, unsigned int vendor, int value);
 int            dict_vendorbyname(const char *name);
 DICT_VENDOR    *dict_vendorbyvalue(int vendor);
 
index cf27616..6850730 100644 (file)
@@ -17,7 +17,7 @@
 
 #ifndef WITHOUT_LIBLTDL
 #ifdef WITH_SYSTEM_LTDL
-#include "ltdl.h"
+#include <ltdl.h>
 #else
 #include "libltdl/ltdl.h"
 #endif
index 74e2a33..e7b5bae 100644 (file)
@@ -31,8 +31,6 @@ RCSIDH(packet_h, "$Id$")
 extern "C" {
 #endif
 
-uint32_t fr_request_packet_hash(const RADIUS_PACKET *packet);
-uint32_t fr_reply_packet_hash(const RADIUS_PACKET *packet);
 int fr_packet_cmp(const RADIUS_PACKET *a, const RADIUS_PACKET *b);
 int fr_inaddr_any(fr_ipaddr_t *ipaddr);
 void fr_request_from_reply(RADIUS_PACKET *request,
index b67f0e8..4311801 100644 (file)
 #define VENDORPEC_FREERADIUS           11344
 #define VENDORPEC_WIMAX                        24757
 #define VENDORPEC_EXTENDED             (1 << 25)
+#define VENDORPEC_UKERNA               25622
 
 /*
  * Vendor specific attributes
 #define PW_VQP_MAC                     0x2c06
 #define PW_VQP_UNKNOWN                 0x2c07
 #define PW_VQP_COOKIE                  0x2c08
+
+/*
+ * JANET's code for transporting eap channel binding data over ttls
+ */
+
+#define PW_UKERNA_CHBIND               134
index 333698a..ffac65f 100644 (file)
@@ -374,7 +374,10 @@ struct fr_tls_server_conf_t {
        int             ocsp_enable;
        int             ocsp_override_url;
        char            *ocsp_url;
+       int             ocsp_use_nonce;
        X509_STORE      *ocsp_store;
+       int             ocsp_timeout;
+       int             ocsp_softfail;
 #endif
 
 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
@@ -382,6 +385,12 @@ struct fr_tls_server_conf_t {
        char            *ecdh_curve;
 #endif
 #endif
+
+#ifdef PSK_MAX_IDENTITY_LEN
+       char            *psk_identity;
+       char            *psk_password;
+#endif
+
 };
 
 #ifdef __cplusplus
diff --git a/src/lib/all.mk b/src/lib/all.mk
new file mode 100644 (file)
index 0000000..15f6c9b
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# Makefile
+#
+# Version:      $Id$
+#
+
+SOURCES                := dict.c filters.c hash.c hmac.c hmacsha1.c isaac.c log.c \
+                 misc.c missing.c md4.c md5.c print.c radius.c rbtree.c \
+                 sha1.c snprintf.c strlcat.c strlcpy.c token.c udpfromto.c \
+                 valuepair.c fifo.c packet.c event.c getaddrinfo.c vqp.c \
+                 heap.c dhcp.c tcp.c
+
+INCLUDES       = ../include/radius.h ../include/libradius.h \
+                 ../include/missing.h ../include/autoconf.h \
+                 ../include/ident.h
+
+SRC_CFLAGS     := -D_LIBRADIUS -I$(top_builddir)/src
+
+TARGET         := libfreeradius-radius.a
index 5b62055..98b8aac 100644 (file)
@@ -244,7 +244,7 @@ RADIUS_PACKET *fr_dhcp_recv(int sockfd)
 
        if (packet->data_len < MIN_PACKET_SIZE) {
                fr_strerror_printf("DHCP packet is too small (%d < %d)",
-                     packet->data_len, MIN_PACKET_SIZE);
+                                  (int) packet->data_len, MIN_PACKET_SIZE);
                rad_free(&packet);
                return NULL;
        }
@@ -1565,6 +1565,11 @@ int fr_dhcp_add_arp_entry(int fd, const char *interface,
 
        return 0;
 #else
+       fd = fd;                /* -Wunused */
+       interface = interface;  /* -Wunused */
+       macaddr = macaddr;      /* -Wunused */
+       ip = ip;                /* -Wunused */
+
        fr_strerror_printf("Adding ARP entry is unsupported on this system");
        return -1;
 #endif
index 71bdfed..9c166b1 100644 (file)
@@ -1413,7 +1413,7 @@ static int process_attribute(const char* fn, const int line,
                /*
                 *      TLV's can be only one octet.
                 */
-               if ((value <= 0) || ((value & ~fr_attr_mask[tlv_depth]) != 0)) {
+               if ((value == 0) || ((value & ~fr_attr_mask[tlv_depth]) != 0)) {
                        fr_strerror_printf( "dict_init: %s[%d]: sub-tlv has invalid attribute number",
                                            fn, line);
                        return -1;
@@ -2301,6 +2301,19 @@ DICT_VALUE *dict_valbyattr(unsigned int attr, unsigned int vendor, int value)
 }
 
 /*
+ *     Associate a value with an attribute and return it.
+ */
+const char *dict_valnamebyattr(unsigned int attr, unsigned int vendor, int value)
+{
+       DICT_VALUE *dv;
+
+       dv = dict_valbyattr(attr, vendor, value);
+       if (!dv) return "";
+
+       return dv->name;
+}
+
+/*
  *     Get a value by its name, keyed off of an attribute.
  */
 DICT_VALUE *dict_valbyname(unsigned int attr, unsigned int vendor, const char *name)
index ad68ce2..813360b 100644 (file)
@@ -32,102 +32,6 @@ RCSID("$Id$")
 #include <fcntl.h>
 
 /*
- *     Take the key fields of a request packet, and convert it to a
- *     hash.
- */
-uint32_t fr_request_packet_hash(const RADIUS_PACKET *packet)
-{
-       uint32_t hash;
-
-       if (packet->hash) return packet->hash;
-
-       hash = fr_hash(&packet->sockfd, sizeof(packet->sockfd));
-       hash = fr_hash_update(&packet->src_port, sizeof(packet->src_port),
-                               hash);
-       hash = fr_hash_update(&packet->dst_port,
-                               sizeof(packet->dst_port), hash);
-       hash = fr_hash_update(&packet->src_ipaddr.af,
-                               sizeof(packet->src_ipaddr.af), hash);
-
-       /*
-        *      The caller ensures that src & dst AF are the same.
-        */
-       switch (packet->src_ipaddr.af) {
-       case AF_INET:
-               hash = fr_hash_update(&packet->src_ipaddr.ipaddr.ip4addr,
-                                       sizeof(packet->src_ipaddr.ipaddr.ip4addr),
-                                       hash);
-               hash = fr_hash_update(&packet->dst_ipaddr.ipaddr.ip4addr,
-                                       sizeof(packet->dst_ipaddr.ipaddr.ip4addr),
-                                       hash);
-               break;
-       case AF_INET6:
-               hash = fr_hash_update(&packet->src_ipaddr.ipaddr.ip6addr,
-                                       sizeof(packet->src_ipaddr.ipaddr.ip6addr),
-                                       hash);
-               hash = fr_hash_update(&packet->dst_ipaddr.ipaddr.ip6addr,
-                                       sizeof(packet->dst_ipaddr.ipaddr.ip6addr),
-                                       hash);
-               break;
-       default:
-               break;
-       }
-
-       return fr_hash_update(&packet->id, sizeof(packet->id), hash);
-}
-
-
-/*
- *     Take the key fields of a reply packet, and convert it to a
- *     hash.
- *
- *     i.e. take a reply packet, and find the hash of the request packet
- *     that asked for the reply.  To do this, we hash the reverse fields
- *     of the request.  e.g. where the request does (src, dst), we do
- *     (dst, src)
- */
-uint32_t fr_reply_packet_hash(const RADIUS_PACKET *packet)
-{
-       uint32_t hash;
-
-       hash = fr_hash(&packet->sockfd, sizeof(packet->sockfd));
-       hash = fr_hash_update(&packet->id, sizeof(packet->id), hash);
-       hash = fr_hash_update(&packet->src_port, sizeof(packet->src_port),
-                               hash);
-       hash = fr_hash_update(&packet->dst_port,
-                               sizeof(packet->dst_port), hash);
-       hash = fr_hash_update(&packet->src_ipaddr.af,
-                               sizeof(packet->src_ipaddr.af), hash);
-
-       /*
-        *      The caller ensures that src & dst AF are the same.
-        */
-       switch (packet->src_ipaddr.af) {
-       case AF_INET:
-               hash = fr_hash_update(&packet->dst_ipaddr.ipaddr.ip4addr,
-                                       sizeof(packet->dst_ipaddr.ipaddr.ip4addr),
-                                       hash);
-               hash = fr_hash_update(&packet->src_ipaddr.ipaddr.ip4addr,
-                                       sizeof(packet->src_ipaddr.ipaddr.ip4addr),
-                                       hash);
-               break;
-       case AF_INET6:
-               hash = fr_hash_update(&packet->dst_ipaddr.ipaddr.ip6addr,
-                                       sizeof(packet->dst_ipaddr.ipaddr.ip6addr),
-                                       hash);
-               hash = fr_hash_update(&packet->src_ipaddr.ipaddr.ip6addr,
-                                       sizeof(packet->src_ipaddr.ipaddr.ip6addr),
-                                       hash);
-               break;
-       default:
-               break;
-       }
-
-       return fr_hash_update(&packet->id, sizeof(packet->id), hash);
-}
-
-
-/*
  *     See if two packets are identical.
  *
  *     Note that we do NOT compare the authentication vectors.
index 7529189..8bcca4f 100644 (file)
@@ -2925,17 +2925,17 @@ static ssize_t data2vp_any(const RADIUS_PACKET *packet,
                 */
        case FLAG_ENCRYPT_USER_PASSWORD:
                if (original) {
-                       rad_pwdecode(buffer,
+                       rad_pwdecode((char *) buffer,
                                     vp->length, secret,
                                     original->vector);
                } else {
-                       rad_pwdecode(buffer,
+                       rad_pwdecode((char *) buffer,
                                     vp->length, secret,
                                     packet->vector);
                }
                buffer[253] = '\0';
                if (vp->attribute == PW_USER_PASSWORD) {
-                       vp->length = strlen(buffer);
+                       vp->length = strlen((char *) buffer);
                }
                break;
 
@@ -2967,7 +2967,7 @@ static ssize_t data2vp_any(const RADIUS_PACKET *packet,
                        memcpy(buffer, my_digest,
                               AUTH_VECTOR_LEN );
                        buffer[AUTH_VECTOR_LEN] = '\0';
-                       vp->length = strlen(buffer);
+                       vp->length = strlen((char *) buffer);
                }
                break;
 
index 62e7bb6..dc06746 100644 (file)
@@ -10,7 +10,7 @@ SERVER_SRCS   = acct.c auth.c client.c conffile.c crypt.c exec.c files.c \
                  session.c threads.c util.c valuepair.c version.c  \
                  xlat.c process.c realms.c evaluate.c vmps.c detail.c
 ifneq ($(OPENSSL_LIBS),)
-SERVER_SRCS    += cb.c tls.c
+SERVER_SRCS    += cb.c tls.c tls_listen.c
 endif
 
 SERVER_OBJS    += $(SERVER_SRCS:.c=.lo)
@@ -27,14 +27,14 @@ CFLAGS              += $(OPENSSL_INCLUDE)
 VFLAGS         = -DRADIUSD_MAJOR_VERSION=$(RADIUSD_MAJOR_VERSION)
 VFLAGS         += -DRADIUSD_MINOR_VERSION=$(RADIUSD_MINOR_VERSION)
 MODULE_LIBS    = $(STATIC_MODULES)
-BINARIES       = radiusd radwho radclient radmin radconf2xml radattr
+BINARIES       = radiusd$(EXEEXT) radwho$(EXEEXT) radclient$(EXEEXT) radmin$(EXEEXT) radconf2xml$(EXEEXT) radattr$(EXEEXT)
 
 #
 #  The RADIUS sniffer
 #
 PCAP_LIBS      = @PCAP_LIBS@
 ifneq ($(PCAP_LIBS),)
-BINARIES       += radsniff
+BINARIES       += radsniff$(EXEEXT)
 endif
 
 #
@@ -66,7 +66,7 @@ all: $(BINARIES)
 
 $(SERVER_OBJS): $(INCLUDES)
 
-radiusd: $(SERVER_OBJS) $(MODULE_OBJS) $(LIBRADIUS)
+radiusd$(EXEEXT): $(SERVER_OBJS) $(MODULE_OBJS) $(LIBRADIUS)
        $(LIBTOOL) --quiet --mode=link $(CC) -export-dynamic -dlopen self \
                $(LDFLAGS) $(LINK_MODE) -o $@ $(SERVER_OBJS)      \
                $(MODULE_LIBS) $(LIBRADIUS) $(LIBS) $(SNMP_LIBS) \
@@ -96,8 +96,6 @@ session.lo: session.c ../include/modules.h
 
 # It's #include'd for simplicity.  This should be fixed...
 listen.lo: listen.c dhcpd.c command.c
-       @echo CC $<
-       @$(LIBTOOL) --quiet --mode=compile $(CC) $(CFLAGS) $(INCLTDL) -c listen.c
 
 #
 # Helper programs
@@ -109,7 +107,7 @@ radclient.lo: radclient.c $(INCLUDES)
 
 MSCHAP_OBJS := ../modules/rlm_mschap/smbdes.lo ../modules/rlm_mschap/mschap.lo 
 
-radclient: radclient.lo $(MSCHAP_OBJS) $(LIBRADIUS)
+radclient$(EXEEXT): radclient.lo $(MSCHAP_OBJS) $(LIBRADIUS)
        @echo LINK $< ...
        @$(LIBTOOL) --quiet --mode=link $(CC) $(LDFLAGS) $(LINK_MODE) -o radclient radclient.lo $(MSCHAP_OBJS) $(LIBRADIUS) $(LIBS)
 
@@ -123,30 +121,30 @@ radclient: radclient.lo $(MSCHAP_OBJS) $(LIBRADIUS)
 
 radsniff.lo: radsniff.c $(INCLUDES) ../include/radsniff.h
 
-radsniff: radsniff.lo $(LIBRADIUS)
+radsniff$(EXEEXT): radsniff.lo $(LIBRADIUS)
        @echo LINK $@ $<
        @$(LIBTOOL) --quiet --mode=link $(CC) $(LDFLAGS) $(LINK_MODE) -o radsniff radsniff.lo $(LIBRADIUS) $(LIBS) $(PCAP_LIBS)
 
 radwho.lo: radwho.c $(INCLUDES)
        $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c radwho.c
 
-radwho: radwho.lo util.lo log.lo conffile.lo $(LIBRADIUS)
+radwho$(EXEEXT): radwho.lo util.lo log.lo conffile.lo $(LIBRADIUS)
        $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LINK_MODE) -o radwho radwho.lo util.lo log.lo conffile.lo $(LIBRADIUS) $(LIBS)
 
-radmin: radmin.lo $(LIBRADIUS) util.lo log.lo conffile.lo
+radmin$(EXEEXT): radmin.lo $(LIBRADIUS) util.lo log.lo conffile.lo
        $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LINK_MODE) -o $@ $^ $(LIBREADLINE) $(LIBS)
 
-radconf2xml: radconf2xml.lo $(LIBRADIUS) util.lo log.lo conffile.lo
+radconf2xml$(EXEEXT): radconf2xml.lo $(LIBRADIUS) util.lo log.lo conffile.lo
        $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LINK_MODE) -o $@ $^ $(LIBS)
 
-radattr: radattr.lo $(LIBRADIUS)
+radattr$(EXEEXT): radattr.lo $(LIBRADIUS)
        $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LINK_MODE) -o radattr radattr.lo $(LIBRADIUS) $(LIBS)
 
 dhclient.lo: dhclient.c $(INCLUDES)
        $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c dhclient.c
 
 # Don't install this for now.
-dhclient: dhclient.lo $(LIBRADIUS)
+dhclient$(EXEEXT): dhclient.lo $(LIBRADIUS)
        $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LINK_MODE) -o dhclient dhclient.lo $(LIBRADIUS) $(LIBS)
 
 clean:
index 09b129f..baeb686 100644 (file)
@@ -87,8 +87,9 @@ int rad_accounting(REQUEST *request)
                 */
                vp = pairfind(request->config_items, PW_ACCT_TYPE, 0);
                if (vp) {
-                       DEBUG2("  Found Acct-Type %s", vp->vp_strvalue);
                        acct_type = vp->vp_integer;
+                       DEBUG2("  Found Acct-Type %s",
+                              dict_valnamebyattr(PW_ACCT_TYPE, 0, acct_type));
                }
                result = module_accounting(acct_type, request);
                switch (result) {
diff --git a/src/main/all.mk b/src/main/all.mk
new file mode 100644 (file)
index 0000000..ff260fc
--- /dev/null
@@ -0,0 +1 @@
+SUBMAKEFILES := radclient.mk radiusd.mk radsniff.mk
index 6a392be..b6215aa 100644 (file)
@@ -112,10 +112,11 @@ static int rad_authlog(const char *msg, REQUEST *request, int goodpass)
 
                        auth_type = pairfind(request->config_items,
                                             PW_AUTH_TYPE, 0);
-                       if (auth_type && (auth_type->vp_strvalue[0] != '\0')) {
+                       if (auth_type) {
                                snprintf(clean_password, sizeof(clean_password),
                                         "<via Auth-Type = %s>",
-                                        auth_type->vp_strvalue);
+                                        dict_valnamebyattr(PW_AUTH_TYPE, 0,
+                                                           auth_type->vp_integer));
                        } else {
                                strcpy(clean_password, "<no User-Password attribute>");
                        }
@@ -184,14 +185,11 @@ static int rad_check_password(REQUEST *request)
         */
        cur_config_item = request->config_items;
        while(((auth_type_pair = pairfind(cur_config_item, PW_AUTH_TYPE, 0))) != NULL) {
-               DICT_VALUE *dv;
                auth_type = auth_type_pair->vp_integer;
                auth_type_count++;
-               dv = dict_valbyattr(PW_AUTH_TYPE,
-                                   auth_type_pair->vp_integer, 0);
 
                RDEBUG2("Found Auth-Type = %s",
-                       (dv != NULL) ? dv->name : "?");
+                       dict_valnamebyattr(PW_AUTH_TYPE, 0, auth_type));
                cur_config_item = auth_type_pair->next;
 
                if (auth_type == PW_AUTHTYPE_REJECT) {
@@ -426,8 +424,9 @@ int rad_postauth(REQUEST *request)
         */
        vp = pairfind(request->config_items, PW_POST_AUTH_TYPE, 0);
        if (vp) {
-               RDEBUG2("Using Post-Auth-Type %s", vp->vp_strvalue);
                postauth_type = vp->vp_integer;
+               RDEBUG2("Using Post-Auth-Type %s",
+                       dict_valnamebyattr(PW_POST_AUTH_TYPE, 0, postauth_type));
        }
        result = module_post_auth(postauth_type, request);
        switch (result) {
@@ -602,8 +601,9 @@ autz_redo:
        if (!autz_retry) {
                tmp = pairfind(request->config_items, PW_AUTZ_TYPE, 0);
                if (tmp) {
-                       RDEBUG2("Using Autz-Type %s", tmp->vp_strvalue);
                        autz_type = tmp->vp_integer;
+                       RDEBUG2("Using Autz-Type %s",
+                               dict_valnamebyattr(PW_AUTZ_TYPE, 0, autz_type));
                        autz_retry = 1;
                        goto autz_redo;
                }
@@ -716,8 +716,9 @@ autz_redo:
 
                tmp = pairfind(request->config_items, PW_SESSION_TYPE, 0);
                if (tmp) {
-                       RDEBUG2("Using Session-Type %s", tmp->vp_strvalue);
                        session_type = tmp->vp_integer;
+                       RDEBUG2("Using Session-Type %s",
+                               dict_valnamebyattr(PW_SESSION_TYPE, 0, session_type));
                }
 
                /*
index 82106c6..22f0cf3 100644 (file)
@@ -88,20 +88,24 @@ pid_t radius_start_program(const char *cmd, REQUEST *request,
                        VALUE_PAIR *input_pairs,
                        int shell_escape)
 {
-       VALUE_PAIR *vp;
-       char mycmd[1024];
        const char *from;
-       char *p, *to;
+       char *to;
+#ifndef __MINGW32__
+       char *p;
+       VALUE_PAIR *vp;
+       int n;
        int to_child[2] = {-1, -1};
        int from_child[2] = {-1, -1};
        pid_t pid;
+#endif
        int argc = -1;
        int i;
-       int n, left;
+       int left;
        char *argv[MAX_ARGV];
        char argv_buf[4096];
 #define MAX_ENVP 1024
        char *envp[MAX_ENVP];
+       char mycmd[1024];
 
        if (strlen(cmd) > (sizeof(mycmd) - 1)) {
                radlog(L_ERR|L_CONS, "Command line is too long");
@@ -423,6 +427,42 @@ pid_t radius_start_program(const char *cmd, REQUEST *request,
        }
 
        return pid;
+#else
+       if (exec_wait) {
+               radlog(L_ERR, "Exec-Program-Wait is not supported");
+               return -1;
+       }
+       
+       {
+               /*
+                *      The _spawn and _exec families of functions are
+                *      found in Windows compiler libraries for
+                *      portability from UNIX. There is a variety of
+                *      functions, including the ability to pass
+                *      either a list or array of parameters, to
+                *      search in the PATH or otherwise, and whether
+                *      or not to pass an environment (a set of
+                *      environment variables). Using _spawn, you can
+                *      also specify whether you want the new process
+                *      to close your program (_P_OVERLAY), to wait
+                *      until the new process is finished (_P_WAIT) or
+                *      for the two to run concurrently (_P_NOWAIT).
+                
+                *      _spawn and _exec are useful for instances in
+                *      which you have simple requirements for running
+                *      the program, don't want the overhead of the
+                *      Windows header file, or are interested
+                *      primarily in portability.
+                */
+
+               /*
+                *      FIXME: check return code... what is it?
+                */
+               _spawnve(_P_NOWAIT, argv[0], argv, envp);
+       }
+
+       return 0;
+#endif
 }
 
 /** Read from the child process.
@@ -434,9 +474,11 @@ pid_t radius_start_program(const char *cmd, REQUEST *request,
  * @param left length of buffer.
  * @return -1 on error, or length of output.
  */
-int radius_readfrom_program(int fd, pid_t pid, int timeout, char *answer, int left) {
-
-       int done;
+int radius_readfrom_program(int fd, pid_t pid, int timeout, char *answer,
+                           int left)
+{
+       int done = 0;
+#ifndef __MINGW32__
        int status;
        struct timeval start;
 #ifdef O_NONBLOCK
@@ -468,7 +510,6 @@ int radius_readfrom_program(int fd, pid_t pid, int timeout, char *answer, int le
         *      Read from the pipe until we doesn't get any more or
         *      until the message is full.
         */
-       done = 0;
        gettimeofday(&start, NULL);
        while (1) {
                int rcode;
@@ -548,7 +589,7 @@ int radius_readfrom_program(int fd, pid_t pid, int timeout, char *answer, int le
                left -= status;
                if (left <= 0) break;
        }
-
+#endif /* __MINGW32__ */
        return done;
 }
 
@@ -574,14 +615,17 @@ int radius_exec_program(const char *cmd, REQUEST *request,
                        VALUE_PAIR **output_pairs,
                        int shell_escape)
 {
+       pid_t pid;
+       int from_child;
+#ifndef __MINGW32__
        VALUE_PAIR *vp;
        char *p;
-       int from_child;
-       pid_t pid, child_pid;
+       pid_t child_pid;
        int comma = 0;
        int status;
        int n, done;
        char answer[4096];
+#endif
 
        pid = radius_start_program(cmd, request, exec_wait, NULL, &from_child, input_pairs, shell_escape);
        if (pid < 0) {
@@ -591,6 +635,7 @@ int radius_exec_program(const char *cmd, REQUEST *request,
        if (!exec_wait)
                return 0;
 
+#ifndef __MINGW32__
        done = radius_readfrom_program(from_child, pid, 10, answer, sizeof(answer));
        if (done < 0) {
                /*
@@ -691,52 +736,9 @@ int radius_exec_program(const char *cmd, REQUEST *request,
 
        radlog(L_ERR|L_CONS, "Exec-Program: Abnormal child exit: %s",
               strerror(errno));
-       return 1;
-#else
-       msg_len = msg_len;      /* -Wunused */
-
-       if (exec_wait) {
-               radlog(L_ERR, "Exec-Program-Wait is not supported");
-               return -1;
-       }
-       
-       /*
-        *      We're not waiting, so we don't look for a
-        *      message, or VP's.
-        */
-       user_msg = NULL;
-       output_pairs = NULL;
+#endif /* __MINGW32__ */
 
-       {
-               /*
-                *      The _spawn and _exec families of functions are
-                *      found in Windows compiler libraries for
-                *      portability from UNIX. There is a variety of
-                *      functions, including the ability to pass
-                *      either a list or array of parameters, to
-                *      search in the PATH or otherwise, and whether
-                *      or not to pass an environment (a set of
-                *      environment variables). Using _spawn, you can
-                *      also specify whether you want the new process
-                *      to close your program (_P_OVERLAY), to wait
-                *      until the new process is finished (_P_WAIT) or
-                *      for the two to run concurrently (_P_NOWAIT).
-                
-                *      _spawn and _exec are useful for instances in
-                *      which you have simple requirements for running
-                *      the program, don't want the overhead of the
-                *      Windows header file, or are interested
-                *      primarily in portability.
-                */
-
-               /*
-                *      FIXME: check return code... what is it?
-                */
-               _spawnve(_P_NOWAIT, argv[0], argv, envp);
-       }
-
-       return 0;
-#endif
+       return 1;
 }
 
 void exec_trigger(REQUEST *request, CONF_SECTION *cs, const char *name)
index cd63bec..446674f 100644 (file)
@@ -561,9 +561,11 @@ static int dual_tcp_accept(rad_listen_t *listener)
                /*
                 *      Non-blocking sockets must handle this.
                 */
+#ifdef EWOULDBLOCK
                if (errno == EWOULDBLOCK) {
                        return 0;
                }
+#endif
 
                DEBUG2(" ... failed to accept connection.");
                return -1;
@@ -2373,9 +2375,7 @@ int proxy_new_listener(home_server *home, int src_port)
 {
        rad_listen_t *this;
        listen_socket_t *sock;
-#ifndef NDEBUG
        char buffer[256];
-#endif
 
        if (!home) return 0;
 
index cf8994b..6a20fd9 100644 (file)
@@ -49,6 +49,9 @@ static const FR_NAME_NUMBER levels[] = {
        { NULL, 0 }
 };
 
+int log_dates_utc = 0;
+
+
 /*
  *     Log the message to the logfile. Include the severity and
  *     a time stamp.
@@ -280,7 +283,14 @@ void radlog_request(int lvl, int priority, REQUEST *request, const char *msg, ..
                time_t timeval;
                timeval = time(NULL);
 
-               CTIME_R(&timeval, buffer + len, sizeof(buffer) - len - 1);
+#ifdef HAVE_GMTIME_R
+               if (log_dates_utc) {
+                       struct tm utc;
+                       gmtime_r(&timeval, &utc);
+                       asctime_r(&utc, buffer + len);
+               } else
+#endif
+                       CTIME_R(&timeval, buffer + len, sizeof(buffer) - len - 1);
                
                s = strrchr(buffer, '\n');
                if (s) {
@@ -288,9 +298,7 @@ void radlog_request(int lvl, int priority, REQUEST *request, const char *msg, ..
                        s[1] = '\0';
                }
                
-               s = fr_int2str(levels, (lvl & ~L_CONS), ": ");
-               
-               strcat(buffer, s);
+               strcat(buffer, fr_int2str(levels, (lvl & ~L_CONS), ": "));
                len = strlen(buffer);
        }
        
index d6986b2..73a8201 100644 (file)
@@ -61,6 +61,7 @@ RCSID("$Id$")
 struct main_config_t mainconfig;
 char *request_log_file = NULL;
 char *debug_condition = NULL;
+extern int log_dates_utc;
 
 typedef struct cached_config_t {
        struct cached_config_t *next;
@@ -185,6 +186,7 @@ static const CONF_PARSER serverdest_config[] = {
        { "log", PW_TYPE_SUBSECTION, 0, NULL, (const void *) logdest_config },
        { "log_file", PW_TYPE_STRING_PTR, 0, &mainconfig.log_file, NULL },
        { "log_destination", PW_TYPE_STRING_PTR, 0, &radlog_dest, NULL },
+       { "use_utc", PW_TYPE_BOOLEAN, 0, &log_dates_utc, NULL },
        { NULL, -1, 0, NULL, NULL }
 };
 
@@ -198,6 +200,8 @@ static const CONF_PARSER log_config_nodest[] = {
        { "msg_badpass", PW_TYPE_STRING_PTR, 0, &mainconfig.auth_badpass_msg, NULL},
        { "msg_goodpass", PW_TYPE_STRING_PTR, 0, &mainconfig.auth_goodpass_msg, NULL},
 
+       { "use_utc", PW_TYPE_BOOLEAN, 0, &log_dates_utc, NULL },
+
        { NULL, -1, 0, NULL, NULL }
 };
 
index fb4f92c..d32b5f7 100644 (file)
@@ -112,7 +112,8 @@ const section_type_value_t section_type_value[RLM_COMPONENT_COUNT] = {
 
 int lt_dlinit(void)
 {
-       char *p, *val;
+       char *p;
+       const char *val;
        char buffer[1024];
 
        /*
index 9056f50..074189d 100644 (file)
@@ -1617,7 +1617,9 @@ retry:
        PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
        
        if (!rcode) {
+#ifdef HAVE_PTHREAD_H
                if (proxy_no_new_sockets) return 0;
+#endif
 
                /*
                 *      Also locks the proxy mutex, so we have to call
@@ -3189,6 +3191,7 @@ static void request_coa_timer(REQUEST *request)
 }
 
 
+#ifdef HAVE_PTHREAD_H
 STATE_MACHINE_DECL(coa_running)
 {
        TRACE_STATE_MACHINE;
@@ -3211,6 +3214,7 @@ STATE_MACHINE_DECL(coa_running)
                break;
        }
 }
+#endif /* HAVE_PTHREAD_H */
 
 
 /*
@@ -3397,7 +3401,9 @@ int event_new_fd(rad_listen_t *this)
                                                       &sock->other_ipaddr, sock->other_port,
                                                       this)) {
 
+#ifdef HAVE_PTHREAD_H
                                proxy_no_new_sockets = TRUE;
+#endif
                                PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
 
                                /*
@@ -3414,6 +3420,7 @@ int event_new_fd(rad_listen_t *this)
                        if (sock->home) {
                                sock->home->num_connections++;
                                
+#ifdef HAVE_PTHREAD_H
                                /*
                                 *      If necessary, add it to the list of
                                 *      new proxy listeners.
@@ -3422,6 +3429,7 @@ int event_new_fd(rad_listen_t *this)
                                        this->next = proxy_listener_list;
                                        proxy_listener_list = this;
                                }
+#endif
                        }
                        PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
 
@@ -3761,6 +3769,7 @@ static void handle_signal_self(int flag)
 
 #ifdef WITH_TCP
 #ifdef WITH_PROXY
+#ifdef HAVE_PTHREAD_H
        /*
         *      Add event handlers for idle timeouts && maximum lifetime.
         */
@@ -3791,6 +3800,7 @@ static void handle_signal_self(int flag)
 
                PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
        }
+#endif /* HAVE_PTHREAD_H */
 #endif /* WITH_PROXY */
 #endif /* WITH_TCP */
 }
diff --git a/src/main/radclient.mk b/src/main/radclient.mk
new file mode 100644 (file)
index 0000000..7750683
--- /dev/null
@@ -0,0 +1,10 @@
+TGT_PREREQS := libfreeradius-radius.a
+SRC_CFLAGS := -I${top_srcdir}/src/modules/rlm_mschap
+SRC_CFLAGS     += -DRADIUSD_VERSION=\"${RADIUSD_VERSION}\"
+
+TGT_LDLIBS := $(LIBS)
+
+SOURCES        := radclient.c ${top_srcdir}/src/modules/rlm_mschap/smbdes.c \
+          ${top_srcdir}/src/modules/rlm_mschap/mschap.c
+
+TARGET := radclient
index 7d9a8eb..bd9f347 100644 (file)
@@ -34,7 +34,7 @@ RCSID("$Id$")
 /*
  *     For configuration file stuff.
  */
-char *radius_dir = RADDBDIR;
+const char *raddb_dir = RADDBDIR;
 const char *progname = "radconf2xml";
 
 /*
@@ -84,7 +84,7 @@ int main(int argc, char **argv)
                                fprintf(stderr, "%s: -d and -f cannot be used together.\n", progname);
                                exit(1);
                        }
-                       radius_dir = optarg;
+                       raddb_dir = optarg;
                        break;
 
                default:
@@ -102,7 +102,7 @@ int main(int argc, char **argv)
                }
        }
 
-       snprintf(buffer, sizeof(buffer), "%s/%s.conf", radius_dir, name);
+       snprintf(buffer, sizeof(buffer), "%s/%s.conf", raddb_dir, name);
        cs = cf_file_read(buffer);
        if (!cs) {
                fprintf(stderr, "%s: Errors reading %s\n",
index 45c75aa..e9cf50f 100644 (file)
@@ -113,7 +113,7 @@ int main(int argc, char *argv[])
        {
                WSADATA wsaData;
                if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
-                       fprintf(stderr, "%s: Unable to initialize socket library.\n");
+                 fprintf(stderr, "%s: Unable to initialize socket library.\n", progname);
                        return 1;
                }
        }
diff --git a/src/main/radiusd.mk b/src/main/radiusd.mk
new file mode 100644 (file)
index 0000000..ba396b0
--- /dev/null
@@ -0,0 +1,68 @@
+SOURCES := acct.c auth.c client.c conffile.c crypt.c exec.c files.c \
+                 listen.c log.c mainconfig.c modules.c modcall.c \
+                 radiusd.c stats.c soh.c connection.c dhcpd.c \
+                 session.c threads.c util.c valuepair.c version.c  \
+                 xlat.c process.c realms.c evaluate.c vmps.c detail.c
+ifneq ($(OPENSSL_LIBS),)
+SOURCES        += cb.c tls.c tls_listen.c
+endif
+
+SRC_CFLAGS     := -DHOSTINFO=\"${HOSTINFO}\"
+SRC_CFLAGS     += -DRADIUSD_VERSION=\"${RADIUSD_VERSION}\"
+SRC_CFLAGS     += $(OPENSSL_INCLUDE)
+TGT_INSTALLDIR  := ${sbindir}
+TGT_LDLIBS     := $(OPENSSL_LIBS)
+TGT_LDFLAGS     := $(LIBS) $(LCRYPT)
+
+TGT_PREREQS    := libfreeradius-radius.a $(filter rlm_%,${ALL_TGTS})
+
+ifneq "${LIBTOOL}" ""
+SRC_FLAGS      += -DWITH_DLOPEN
+else
+${DIR}/modules.c:      ${BUILD_DIR}/make/include/lt_dlmodules.c
+
+# Find the modules
+ALL_MODULES    := $(patsubst %.a,%,$(filter rlm_%,${ALL_TGTS}))
+ALL_MODULES    := $(patsubst %.la,%,$(filter rlm_%,${ALL_MODULES}))
+
+# Filter out ones with additional library dependencies.
+# For the future, go through ALL modules and add their library dependencies
+# to the TGT_LDLIBS.
+ALL_MODULES    := $(filter-out rlm_perl rlm_ldap rlm_pam rlm_krb5 rlm_python,${ALL_MODULES})
+
+# EAP and SQL require different variable declarations.
+EAP_MODULES    := $(filter rlm_eap_%,${ALL_MODULES})
+SQL_MODULES    := $(filter rlm_sql_%,${ALL_MODULES})
+
+BASE_MODULES   := $(filter-out ${EAP_MODULES} ${SQL_MODULES},${ALL_MODULES})
+
+#
+#  Create the intermediate file which links to the modules.
+#  And have it depend on this Makefile, which creates it.
+#
+${BUILD_DIR}/make/include/lt_dlmodules.c: $(addprefix ${BUILD_DIR}/lib/,$(filter rlm_%,${ALL_TGTS})) $(lastword ${MAKEFILE_LIST})
+       @rm -f $@
+       @for x in ${BASE_MODULES}; do \
+               echo "extern module_t $$x;" >> $@; \
+       done
+       @for x in ${EAP_MODULES}; do \
+               echo "extern EAP_TYPE $$x;" >> $@; \
+       done
+       @for x in ${SQL_MODULES}; do \
+               echo "extern rlm_sql_module_t $$x;" >> $@; \
+       done
+       @echo "static const lt_dlmodule_t lt_dlmodules[] = {" >> $@
+       @for x in ${ALL_MODULES}; do \
+               echo "{ \"$$x\", &$$x }," >> $@; \
+       done
+       @echo "{ NULL, NULL }" >> $@
+       @echo "};" >> $@
+endif
+
+# Libraries can't depend on libraries (oops), so make the binary
+# depend on the EAP code...
+ifneq "$(filter rlm_eap_%,${ALL_TGTS})" ""
+TGT_PREREQS    += libfreeradius-eap.a
+endif
+
+TARGET         := radiusd
index c5d5db4..5da57c5 100644 (file)
@@ -527,7 +527,7 @@ int main(int argc, char *argv[])
                exit(1);
 
        } else {
-               descr = pcap_open_live(dev, 65536, 1, 0, errbuf);
+               descr = pcap_open_live(dev, 65536, 1, 1, errbuf);
        }
        if (descr == NULL)
        {
diff --git a/src/main/radsniff.mk.in b/src/main/radsniff.mk.in
new file mode 100644 (file)
index 0000000..5f04d71
--- /dev/null
@@ -0,0 +1,10 @@
+TGT_PREREQS := libfreeradius-radius.a
+TGT_LDLIBS := $(LIBS) @PCAP_LIBS@
+
+SOURCES        := radsniff.c
+
+ifneq ($(PCAP_LIBS),)
+TARGET := radsniff
+else
+TARGET  :=
+endif
index f906d57..437ed8d 100644 (file)
@@ -68,7 +68,7 @@ const char *radlog_dir = NULL;
 const char *radutmp_file = NULL;
 int check_config = FALSE;
 
-char *radius_dir = NULL;
+const char *raddb_dir = NULL;
 const char *radacct_dir = NULL;
 const char *radlib_dir = NULL;
 uint32_t myip = INADDR_ANY;
@@ -270,6 +270,7 @@ static void NEVER_RETURNS usage(int status)
        fprintf(output, "       -d: set the raddb directory (default is %s)\n",
                RADIUS_DIR);
        fprintf(output, "       -f: give fingerd output\n");
+       fprintf(output, "       -F <file>: Use radutmp <file>\n");
        fprintf(output, "       -i: show session ID\n");
        fprintf(output, "       -n: no full name\n");
        fprintf(output, "       -N <nas-ip-address>: Show entries matching the given NAS IP address\n");
@@ -316,16 +317,19 @@ int main(int argc, char **argv)
        uint32_t nas_ip_address = INADDR_NONE;
        int zap = 0;
 
-       radius_dir = RADIUS_DIR;
+       raddb_dir = RADIUS_DIR;
 
-       while((c = getopt(argc, argv, "d:fnN:sSipP:crRu:U:Z")) != EOF) switch(c) {
+       while((c = getopt(argc, argv, "d:fF:nN:sSipP:crRu:U:Z")) != EOF) switch(c) {
                case 'd':
-                       radius_dir = optarg;
+                       raddb_dir = optarg;
                        break;
                case 'f':
                        fingerd++;
                        showname = 0;
                        break;
+               case 'F':
+                       radutmp_file = optarg;
+                       break;
                case 'h':
                        usage(0);
                        break;
@@ -400,6 +404,8 @@ int main(int argc, char **argv)
                exit(0);        /* don't bother printing anything else */
        }
 
+       if (radutmp_file) goto have_radutmp;
+
        /*
         *      Initialize mainconfig
         */
@@ -407,7 +413,7 @@ int main(int argc, char **argv)
        mainconfig.radlog_dest = RADLOG_STDOUT;
 
         /* Read radiusd.conf */
-       snprintf(buffer, sizeof(buffer), "%.200s/radiusd.conf", radius_dir);
+       snprintf(buffer, sizeof(buffer), "%.200s/radiusd.conf", raddb_dir);
        maincs = cf_file_read(buffer);
        if (!maincs) {
                fprintf(stderr, "%s: Error reading radiusd.conf.\n", argv[0]);
@@ -415,7 +421,7 @@ int main(int argc, char **argv)
        }
 
         /* Read the radutmp section of radiusd.conf */
-        cs = cf_section_sub_find(cf_section_sub_find(maincs, "modules"), "radutmp");
+        cs = cf_section_find_name2(cf_section_sub_find(maincs, "modules"), "radutmp", NULL);
         if(!cs) {
                 fprintf(stderr, "%s: No configuration information in radutmp section of radiusd.conf!\n",
                         argv[0]);
@@ -427,6 +433,7 @@ int main(int argc, char **argv)
        /* Assign the correct path for the radutmp file */
        radutmp_file = radutmpconfig.radutmp_fn;
 
+ have_radutmp:
        /*
         *      See if we are "fingerd".
         */
index c820045..9c8b9fb 100644 (file)
@@ -597,9 +597,22 @@ static int home_server_add(realm_config_t *rc, CONF_SECTION *cs)
        } else if (strcasecmp(hs_check, "request") == 0) {
                home->ping_check = HOME_PING_CHECK_REQUEST;
 
+               if (!home->ping_user_name ||
+                   !*home->ping_user_name) {
+                       cf_log_err(cf_sectiontoitem(cs), "You must supply a 'username' to enable status_check=request");
+                       goto error;
+               }
+
+               if ((home->type == HOME_TYPE_AUTH) &&
+                   (!home->ping_user_password ||
+                    !*home->ping_user_password)) {
+                       cf_log_err(cf_sectiontoitem(cs), "You must supply a password to enable status_check=request");
+                       goto error;
+               }
+
        } else {
                cf_log_err(cf_sectiontoitem(cs),
-                          "Invalid ping_check \"%s\" for home server %s.",
+                          "Invalid status__check \"%s\" for home server %s.",
                           hs_check, name2);
                goto error;
        }
@@ -609,13 +622,13 @@ static int home_server_add(realm_config_t *rc, CONF_SECTION *cs)
        if ((home->ping_check != HOME_PING_CHECK_NONE) &&
            (home->ping_check != HOME_PING_CHECK_STATUS_SERVER)) {
                if (!home->ping_user_name) {
-                       cf_log_err(cf_sectiontoitem(cs), "You must supply a user name to enable ping checks");
+                       cf_log_err(cf_sectiontoitem(cs), "You must supply a user name to enable status_check=request");
                        goto error;
                }
 
                if ((home->type == HOME_TYPE_AUTH) &&
                    !home->ping_user_password) {
-                       cf_log_err(cf_sectiontoitem(cs), "You must supply a password to enable ping checks");
+                       cf_log_err(cf_sectiontoitem(cs), "You must supply a password to enable status_check=request");
                        goto error;
                }
        }
@@ -1630,8 +1643,9 @@ static int realm_add(realm_config_t *rc, CONF_SECTION *cs)
                        return 0;
                }
 
-               if (!auth_pool || auth_pool_name &&
-                   (strcmp(auth_pool_name, acct_pool_name) != 0)) {
+               if (!auth_pool ||
+                   (auth_pool_name &&
+                    (strcmp(auth_pool_name, acct_pool_name) != 0))) {
                        do_print = TRUE;
                }
 
index 9e19167..52b216a 100644 (file)
@@ -40,6 +40,7 @@ RCSID("$Id$")
 #include <dispatch/dispatch.h>
 #endif
 #include <mach/task.h>
+#include <mach/mach_init.h>
 #include <mach/semaphore.h>
 
 #undef sem_t
index 10caec4..9d029a8 100644 (file)
@@ -43,15 +43,6 @@ RCSID("$Id$")
 #include <openssl/ocsp.h>
 #endif
 
-#ifdef HAVE_PTHREAD_H
-#define PTHREAD_MUTEX_LOCK pthread_mutex_lock
-#define PTHREAD_MUTEX_UNLOCK pthread_mutex_unlock
-#else
-#define PTHREAD_MUTEX_LOCK(_x)
-#define PTHREAD_MUTEX_UNLOCK(_x)
-#endif
-
-
 /* record */
 static void            record_init(record_t *buf);
 static void            record_close(record_t *buf);
@@ -60,6 +51,51 @@ static unsigned int  record_plus(record_t *buf, const void *ptr,
 static unsigned int    record_minus(record_t *buf, void *ptr,
                                     unsigned int size);
 
+#ifdef PSK_MAX_IDENTITY_LEN
+static unsigned int psk_server_callback(SSL *ssl, const char *identity,
+                                       unsigned char *psk, int max_psk_len)
+{
+       unsigned int psk_len;
+       fr_tls_server_conf_t *conf;
+
+       conf = (fr_tls_server_conf_t *)SSL_get_ex_data(ssl,
+                                                      FR_TLS_EX_INDEX_CONF);
+       if (!conf) return 0;
+
+       /*
+        *      FIXME: Look up the PSK password based on the identity!
+        */
+       if (strcmp(identity, conf->psk_identity) != 0) {
+               return 0;
+       }
+
+       psk_len = strlen(conf->psk_password);
+       if (psk_len > (2 * max_psk_len)) return 0;
+
+       return fr_hex2bin(conf->psk_password, psk, psk_len);
+}
+
+static unsigned int psk_client_callback(SSL *ssl, UNUSED const char *hint,
+                                       char *identity, unsigned int max_identity_len,
+                                       unsigned char *psk, unsigned int max_psk_len)
+{
+       unsigned int psk_len;
+       fr_tls_server_conf_t *conf;
+
+       conf = (fr_tls_server_conf_t *)SSL_get_ex_data(ssl,
+                                                      FR_TLS_EX_INDEX_CONF);
+       if (!conf) return 0;
+
+       psk_len = strlen(conf->psk_password);
+       if (psk_len > (2 * max_psk_len)) return 0;
+
+       strlcpy(identity, conf->psk_identity, max_identity_len);
+
+       return fr_hex2bin(conf->psk_password, psk, psk_len);
+}
+
+#endif
+
 tls_session_t *tls_new_client_session(fr_tls_server_conf_t *conf, int fd)
 {
        int verify_mode;
@@ -734,6 +770,12 @@ static CONF_PARSER ocsp_config[] = {
          offsetof(fr_tls_server_conf_t, ocsp_override_url), NULL, "no"},
        { "url", PW_TYPE_STRING_PTR,
          offsetof(fr_tls_server_conf_t, ocsp_url), NULL, NULL },
+       { "use_nonce", PW_TYPE_BOOLEAN,
+         offsetof(fr_tls_server_conf_t, ocsp_use_nonce), NULL, "yes"},
+       { "timeout", PW_TYPE_INTEGER,
+         offsetof(fr_tls_server_conf_t, ocsp_timeout), NULL, "yes"},
+       { "softfail", PW_TYPE_BOOLEAN,
+         offsetof(fr_tls_server_conf_t, ocsp_softfail), NULL, "yes"},
        { NULL, -1, 0, NULL, NULL }           /* end the list */
 };
 #endif
@@ -761,6 +803,12 @@ static CONF_PARSER tls_server_config[] = {
          offsetof(fr_tls_server_conf_t, ca_file), NULL, NULL },
        { "private_key_password", PW_TYPE_STRING_PTR,
          offsetof(fr_tls_server_conf_t, private_key_password), NULL, NULL },
+#ifdef PSK_MAX_IDENTITY_LEN
+       { "psk_identity", PW_TYPE_STRING_PTR,
+         offsetof(fr_tls_server_conf_t, psk_identity), NULL, NULL },
+       { "psk_hexphrase", PW_TYPE_STRING_PTR,
+         offsetof(fr_tls_server_conf_t, psk_password), NULL, NULL },
+#endif
        { "dh_file", PW_TYPE_STRING_PTR,
          offsetof(fr_tls_server_conf_t, dh_file), NULL, NULL },
        { "random_file", PW_TYPE_STRING_PTR,
@@ -916,8 +964,6 @@ static int generate_eph_rsa_key(SSL_CTX *ctx)
 
 static void cbtls_remove_session(UNUSED SSL_CTX *ctx, SSL_SESSION *sess)
 {
-       int i;
-
        size_t size;
        char buffer[2 * MAX_SESSION_SIZE + 1];
 
@@ -1006,7 +1052,7 @@ static int ocsp_check(X509_STORE *store, X509 *issuer_cert, X509 *client_cert,
 {
        OCSP_CERTID *certid;
        OCSP_REQUEST *req;
-       OCSP_RESPONSE *resp;
+       OCSP_RESPONSE *resp = NULL;
        OCSP_BASICRESP *bresp = NULL;
        char *host = NULL;
        char *port = NULL;
@@ -1018,6 +1064,12 @@ static int ocsp_check(X509_STORE *store, X509 *issuer_cert, X509 *client_cert,
        int status ;
        ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
        int reason;
+#if OPENSSL_VERSION_NUMBER >= 0x1000003f
+       OCSP_REQ_CTX *ctx;
+       int rc;
+       struct timeval now;
+       struct timeval when;
+#endif
 
        /*
         * Create OCSP Request
@@ -1025,7 +1077,9 @@ static int ocsp_check(X509_STORE *store, X509 *issuer_cert, X509 *client_cert,
        certid = OCSP_cert_to_id(NULL, client_cert, issuer_cert);
        req = OCSP_REQUEST_new();
        OCSP_request_add0_id(req, certid);
-       OCSP_request_add1_nonce(req, NULL, 8);
+       if(conf->ocsp_use_nonce) {
+               OCSP_request_add1_nonce(req, NULL, 8);
+       }
 
        /*
         * Send OCSP Request and get OCSP Response
@@ -1047,15 +1101,61 @@ static int ocsp_check(X509_STORE *store, X509 *issuer_cert, X509 *client_cert,
        bio_out = BIO_new_fp(stdout, BIO_NOCLOSE);
 
        BIO_set_conn_port(cbio, port);
+#if OPENSSL_VERSION_NUMBER < 0x1000003f
        BIO_do_connect(cbio);
-
        /* Send OCSP request and wait for response */
        resp = OCSP_sendreq_bio(cbio, path, req);
-       if(resp==0) {
+       if (!resp) {
                radlog(L_ERR, "Error: Couldn't get OCSP response");
+               ocsp_ok = 2;
+               goto ocsp_end;
+       }
+#else
+       if (conf->ocsp_timeout)
+               BIO_set_nbio(cbio, 1);
+
+       rc = BIO_do_connect(cbio);
+       if ((rc <= 0) && ((!conf->ocsp_timeout) || !BIO_should_retry(cbio))) {
+               radlog(L_ERR, "Error: Couldn't connect to OCSP responder");
+               ocsp_ok = 2;
                goto ocsp_end;
        }
 
+       ctx = OCSP_sendreq_new(cbio, path, req, -1);
+       if (!ctx) {
+               radlog(L_ERR, "Error: Couldn't send OCSP request");
+               ocsp_ok = 2;
+               goto ocsp_end;
+       }
+
+       gettimeofday(&when, NULL);
+       when.tv_sec += conf->ocsp_timeout;
+
+       do {
+               rc = OCSP_sendreq_nbio(&resp, ctx);
+               if (conf->ocsp_timeout) {
+                       gettimeofday(&now, NULL);
+                       if (!timercmp(&now, &when, <))
+                               break;
+               }
+       } while ((rc == -1) && BIO_should_retry(cbio));
+
+       if (conf->ocsp_timeout && (rc == -1) && BIO_should_retry(cbio)) {
+               radlog(L_ERR, "Error: OCSP response timed out");
+               ocsp_ok = 2;
+               goto ocsp_end;
+       }
+
+       OCSP_REQ_CTX_free(ctx);
+
+       if (rc == 0) {
+               radlog(L_ERR, "Error: Couldn't get OCSP response");
+               ocsp_ok = 2;
+               goto ocsp_end;
+       }
+#endif
+
        /* Verify OCSP response status */
        status = OCSP_response_status(resp);
        DEBUG2("[ocsp] --> Response status: %s",OCSP_response_status_str(status));
@@ -1064,7 +1164,7 @@ static int ocsp_check(X509_STORE *store, X509 *issuer_cert, X509 *client_cert,
                goto ocsp_end;
        }
        bresp = OCSP_response_get1_basic(resp);
-       if(OCSP_check_nonce(req, bresp)!=1) {
+       if(conf->ocsp_use_nonce && OCSP_check_nonce(req, bresp)!=1) {
                radlog(L_ERR, "Error: OCSP response has wrong nonce value");
                goto ocsp_end;
        }
@@ -1119,10 +1219,23 @@ ocsp_end:
        BIO_free_all(cbio);
        OCSP_BASICRESP_free(bresp);
 
-       if (ocsp_ok) {
+       switch (ocsp_ok) {
+       case 1:
                DEBUG2("[ocsp] --> Certificate is valid!");
-       } else {
+               break;
+       case 2:
+               if (conf->ocsp_softfail) {
+                       DEBUG2("[ocsp] --> Unable to check certificate; assuming valid.");
+                       DEBUG2("[ocsp] --> Warning! This may be insecure.");
+                       ocsp_ok = 1;
+               } else {
+                       DEBUG2("[ocsp] --> Unable to check certificate; failing!");
+                       ocsp_ok = 0;
+               }
+               break;
+       default:
                DEBUG2("[ocsp] --> Certificate has been expired/revoked!");
+               break;
        }
 
        return ocsp_ok;
@@ -1586,7 +1699,7 @@ static void sess_free_vps(UNUSED void *parent, void *data_ptr,
  *     - Load the Private key & the certificate
  *     - Set the Context options & Verify options
  */
-static SSL_CTX *init_tls_ctx(fr_tls_server_conf_t *conf)
+static SSL_CTX *init_tls_ctx(fr_tls_server_conf_t *conf, int client)
 {
        const SSL_METHOD *meth;
        SSL_CTX *ctx;
@@ -1674,6 +1787,53 @@ static SSL_CTX *init_tls_ctx(fr_tls_server_conf_t *conf)
                SSL_CTX_set_default_passwd_cb(ctx, cbtls_password);
        }
 
+#ifdef PSK_MAX_IDENTITY_LEN
+       if ((conf->psk_identity && !conf->psk_password) ||
+           (!conf->psk_identity && conf->psk_password) ||
+           (conf->psk_identity && !*conf->psk_identity) ||
+           (conf->psk_password && !*conf->psk_password)) {
+               radlog(L_ERR, "Invalid PSK Configuration: psk_identity or psk_password are empty");
+               return NULL;
+       }
+
+       if (conf->psk_identity) {
+               size_t psk_len, hex_len;
+               char buffer[PSK_MAX_PSK_LEN];
+
+               if (conf->certificate_file ||
+                   conf->private_key_password || conf->private_key_file ||
+                   conf->ca_file || conf->ca_path) {
+                       radlog(L_ERR, "When PSKs are used, No certificate configuration is permitted");
+                       return NULL;
+               }
+
+               if (client) {
+                       SSL_CTX_set_psk_client_callback(ctx,
+                                                       psk_client_callback);
+               } else {
+                       SSL_CTX_set_psk_server_callback(ctx,
+                                                       psk_server_callback);
+               }
+
+               psk_len = strlen(conf->psk_password);
+               if (strlen(conf->psk_password) > (2 * PSK_MAX_PSK_LEN)) {
+                       radlog(L_ERR, "psk_hexphrase is too long (max %d)",
+                              PSK_MAX_PSK_LEN);
+                       return NULL;                        
+               }
+
+               hex_len = fr_hex2bin(conf->psk_password, buffer, psk_len);
+               if (psk_len != (2 * hex_len)) {
+                       radlog(L_ERR, "psk_hexphrase is not all hex");
+                       return NULL;                        
+               }
+
+               goto post_ca;
+       }
+#else
+       client = client;        /* -Wunused */
+#endif
+
        /*
         *      Load our keys and certificates
         *
@@ -1728,6 +1888,10 @@ load_ca:
                }
        }
 
+#ifdef PSK_MAX_IDENTITY_LEN
+post_ca:
+#endif
+
        /*
         *      Set ctx_options
         */
@@ -1963,7 +2127,7 @@ fr_tls_server_conf_t *tls_server_conf_parse(CONF_SECTION *cs)
        /*
         *      Initialize TLS
         */
-       conf->ctx = init_tls_ctx(conf);
+       conf->ctx = init_tls_ctx(conf, 0);
        if (conf->ctx == NULL) {
                goto error;
        }
@@ -2026,7 +2190,7 @@ fr_tls_server_conf_t *tls_client_conf_parse(CONF_SECTION *cs)
        /*
         *      Initialize TLS
         */
-       conf->ctx = init_tls_ctx(conf);
+       conf->ctx = init_tls_ctx(conf, 1);
        if (conf->ctx == NULL) {
                goto error;
        }
@@ -2289,571 +2453,4 @@ fr_tls_status_t tls_ack_handler(tls_session_t *ssn, REQUEST *request)
        }
 }
 
-static void dump_hex(const char *msg, const uint8_t *data, size_t data_len)
-{
-       size_t i;
-
-       if (debug_flag < 3) return;
-
-       printf("%s %d\n", msg, (int) data_len);
-       if (data_len > 256) data_len = 256;
-
-       for (i = 0; i < data_len; i++) {
-               if ((i & 0x0f) == 0x00) printf ("%02x: ", (unsigned int) i);
-               printf("%02x ", data[i]);
-               if ((i & 0x0f) == 0x0f) printf ("\n");
-       }
-       printf("\n");
-       fflush(stdout);
-}
-
-static void tls_socket_close(rad_listen_t *listener)
-{
-       listen_socket_t *sock = listener->data;
-
-       listener->status = RAD_LISTEN_STATUS_REMOVE_FD;
-       listener->tls = NULL; /* parent owns this! */
-       
-       if (sock->parent) {
-               /*
-                *      Decrement the number of connections.
-                */
-               if (sock->parent->num_connections > 0) {
-                       sock->parent->num_connections--;
-               }
-               if (sock->client->num_connections > 0) {
-                       sock->client->num_connections--;
-               }
-       }
-       
-       /*
-        *      Tell the event handler that an FD has disappeared.
-        */
-       DEBUG("Client has closed connection");
-       event_new_fd(listener);
-       
-       /*
-        *      Do NOT free the listener here.  It's in use by
-        *      a request, and will need to hang around until
-        *      all of the requests are done.
-        *
-        *      It is instead free'd in remove_from_request_hash()
-        */
-}
-
-static int tls_socket_write(rad_listen_t *listener, REQUEST *request)
-{
-       uint8_t *p;
-       ssize_t rcode;
-       listen_socket_t *sock = listener->data;
-
-       p = sock->ssn->dirty_out.data;
-       
-       while (p < (sock->ssn->dirty_out.data + sock->ssn->dirty_out.used)) {
-               RDEBUG3("Writing to socket %d", request->packet->sockfd);
-               rcode = write(request->packet->sockfd, p,
-                             (sock->ssn->dirty_out.data + sock->ssn->dirty_out.used) - p);
-               if (rcode <= 0) {
-                       RDEBUG("Error writing to TLS socket: %s", strerror(errno));
-                       
-                       tls_socket_close(listener);
-                       return 0;
-               }
-               p += rcode;
-       }
-
-       sock->ssn->dirty_out.used = 0;
-       
-       return 1;
-}
-
-
-static int tls_socket_recv(rad_listen_t *listener)
-{
-       int doing_init = FALSE;
-       ssize_t rcode;
-       RADIUS_PACKET *packet;
-       REQUEST *request;
-       listen_socket_t *sock = listener->data;
-       fr_tls_status_t status;
-       RADCLIENT *client = sock->client;
-
-       if (!sock->packet) {
-               sock->packet = rad_alloc(0);
-               if (!sock->packet) return 0;
-
-               sock->packet->sockfd = listener->fd;
-               sock->packet->src_ipaddr = sock->other_ipaddr;
-               sock->packet->src_port = sock->other_port;
-               sock->packet->dst_ipaddr = sock->my_ipaddr;
-               sock->packet->dst_port = sock->my_port;
-
-               if (sock->request) sock->request->packet = sock->packet;
-       }
-
-       /*
-        *      Allocate a REQUEST for debugging.
-        */
-       if (!sock->request) {
-               sock->request = request = request_alloc();
-               if (!sock->request) {
-                       radlog(L_ERR, "Out of memory");
-                       return 0;
-               }
-
-               rad_assert(request->packet == NULL);
-               rad_assert(sock->packet != NULL);
-               request->packet = sock->packet;
-
-               request->component = "<core>";
-               request->component = "<tls-connect>";
-
-               /*
-                *      Not sure if we should do this on every packet...
-                */
-               request->reply = rad_alloc(0);
-               if (!request->reply) return 0;
-
-               request->options = RAD_REQUEST_OPTION_DEBUG2;
-
-               rad_assert(sock->ssn == NULL);
-
-               sock->ssn = tls_new_session(listener->tls, sock->request,
-                                           listener->tls->require_client_cert);
-               if (!sock->ssn) {
-                       request_free(&sock->request);
-                       sock->packet = NULL;
-                       return 0;
-               }
-
-               SSL_set_ex_data(sock->ssn->ssl, FR_TLS_EX_INDEX_REQUEST, (void *)request);
-               SSL_set_ex_data(sock->ssn->ssl, FR_TLS_EX_INDEX_CERTS, (void *)&request->packet->vps);
-
-               doing_init = TRUE;
-       }
-
-       rad_assert(sock->request != NULL);
-       rad_assert(sock->request->packet != NULL);
-       rad_assert(sock->packet != NULL);
-       rad_assert(sock->ssn != NULL);
-
-       request = sock->request;
-
-       RDEBUG3("Reading from socket %d", request->packet->sockfd);
-       PTHREAD_MUTEX_LOCK(&sock->mutex);
-       rcode = read(request->packet->sockfd,
-                    sock->ssn->dirty_in.data,
-                    sizeof(sock->ssn->dirty_in.data));
-       if ((rcode < 0) && (errno == ECONNRESET)) {
-       do_close:
-               PTHREAD_MUTEX_UNLOCK(&sock->mutex);
-               tls_socket_close(listener);
-               return 0;
-       }
-       
-       if (rcode < 0) {
-               RDEBUG("Error reading TLS socket: %s", strerror(errno));
-               goto do_close;
-       }
-
-       /*
-        *      Normal socket close.
-        */
-       if (rcode == 0) goto do_close;
-       
-       sock->ssn->dirty_in.used = rcode;
-       memset(sock->ssn->dirty_in.data + sock->ssn->dirty_in.used,
-              0, 16);
-
-       dump_hex("READ FROM SSL", sock->ssn->dirty_in.data, sock->ssn->dirty_in.used);
-
-       /*
-        *      Catch attempts to use non-SSL.
-        */
-       if (doing_init && (sock->ssn->dirty_in.data[0] != handshake)) {
-               RDEBUG("Non-TLS data sent to TLS socket: closing");
-               goto do_close;
-       }
-       
-       /*
-        *      Skip ahead to reading application data.
-        */
-       if (SSL_is_init_finished(sock->ssn->ssl)) goto app;
-
-       if (!tls_handshake_recv(request, sock->ssn)) {
-               RDEBUG("FAILED in TLS handshake receive");
-               goto do_close;
-       }
-       
-       if (sock->ssn->dirty_out.used > 0) {
-               tls_socket_write(listener, request);
-               PTHREAD_MUTEX_UNLOCK(&sock->mutex);
-               return 0;
-       }
-
-app:
-       /*
-        *      FIXME: Run the packet through a virtual server in
-        *      order to see if we like the certificate presented by
-        *      the client.
-        */
-
-       status = tls_application_data(sock->ssn, request);
-       RDEBUG("Application data status %d", status);
-
-       if (status == FR_TLS_MORE_FRAGMENTS) {
-               PTHREAD_MUTEX_UNLOCK(&sock->mutex);
-               return 0;
-       }
-
-       if (sock->ssn->clean_out.used == 0) {
-               PTHREAD_MUTEX_UNLOCK(&sock->mutex);
-               return 0;
-       }
-
-       dump_hex("TUNNELED DATA", sock->ssn->clean_out.data, sock->ssn->clean_out.used);
-
-       /*
-        *      If the packet is a complete RADIUS packet, return it to
-        *      the caller.  Otherwise...
-        */
-       if ((sock->ssn->clean_out.used < 20) ||
-           (((sock->ssn->clean_out.data[2] << 8) | sock->ssn->clean_out.data[3]) != (int) sock->ssn->clean_out.used)) {
-               RDEBUG("Received bad packet: Length %d contents %d",
-                      sock->ssn->clean_out.used,
-                      (sock->ssn->clean_out.data[2] << 8) | sock->ssn->clean_out.data[3]);
-               goto do_close;
-       }
-
-       packet = sock->packet;
-       packet->data = rad_malloc(sock->ssn->clean_out.used);
-       packet->data_len = sock->ssn->clean_out.used;
-       record_minus(&sock->ssn->clean_out, packet->data, packet->data_len);
-       packet->vps = NULL;
-       PTHREAD_MUTEX_UNLOCK(&sock->mutex);
-
-       if (!rad_packet_ok(packet, 0)) {
-               RDEBUG("Received bad packet: %s", fr_strerror());
-               tls_socket_close(listener);
-               return 0;       /* do_close unlocks the mutex */
-       }
-
-       /*
-        *      Copied from src/lib/radius.c, rad_recv();
-        */
-       if (fr_debug_flag) {
-               char host_ipaddr[128];
-
-               if ((packet->code > 0) && (packet->code < FR_MAX_PACKET_CODE)) {
-                       RDEBUG("tls_recv: %s packet from host %s port %d, id=%d, length=%d",
-                              fr_packet_codes[packet->code],
-                              inet_ntop(packet->src_ipaddr.af,
-                                        &packet->src_ipaddr.ipaddr,
-                                        host_ipaddr, sizeof(host_ipaddr)),
-                              packet->src_port,
-                              packet->id, (int) packet->data_len);
-               } else {
-                       RDEBUG("tls_recv: Packet from host %s port %d code=%d, id=%d, length=%d",
-                              inet_ntop(packet->src_ipaddr.af,
-                                        &packet->src_ipaddr.ipaddr,
-                                        host_ipaddr, sizeof(host_ipaddr)),
-                              packet->src_port,
-                              packet->code,
-                              packet->id, (int) packet->data_len);
-               }
-       }
-
-       FR_STATS_INC(auth, total_requests);
-
-       return 1;
-}
-
-
-int dual_tls_recv(rad_listen_t *listener)
-{
-       RADIUS_PACKET *packet;
-       REQUEST *request;
-       RAD_REQUEST_FUNP fun = NULL;
-       listen_socket_t *sock = listener->data;
-       RADCLIENT       *client = sock->client;
-
-       if (!tls_socket_recv(listener)) {
-               return 0;
-       }
-
-       rad_assert(sock->request != NULL);
-       rad_assert(sock->request->packet != NULL);
-       rad_assert(sock->packet != NULL);
-       rad_assert(sock->ssn != NULL);
-
-       request = sock->request;
-       packet = sock->packet;
-
-       /*
-        *      Some sanity checks, based on the packet code.
-        */
-       switch(packet->code) {
-       case PW_AUTHENTICATION_REQUEST:
-               if (listener->type != RAD_LISTEN_AUTH) goto bad_packet;
-               FR_STATS_INC(auth, total_requests);
-               fun = rad_authenticate;
-               break;
-
-       case PW_ACCOUNTING_REQUEST:
-               if (listener->type != RAD_LISTEN_ACCT) goto bad_packet;
-               FR_STATS_INC(acct, total_requests);
-               fun = rad_accounting;
-               break;
-
-       case PW_STATUS_SERVER:
-               if (!mainconfig.status_server) {
-                       FR_STATS_INC(auth, total_unknown_types);
-                       DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
-                       rad_free(&sock->packet);
-                       request->packet = NULL;
-                       return 0;
-               }
-               fun = rad_status_server;
-               break;
-
-       default:
-       bad_packet:
-               FR_STATS_INC(auth, total_unknown_types);
-
-               DEBUG("Invalid packet code %d sent from client %s port %d : IGNORED",
-                     packet->code, client->shortname, packet->src_port);
-               rad_free(&sock->packet);
-               request->packet = NULL;
-               return 0;
-       } /* switch over packet types */
-
-       if (!request_receive(listener, packet, client, fun)) {
-               FR_STATS_INC(auth, total_packets_dropped);
-               rad_free(&sock->packet);
-               request->packet = NULL;
-               return 0;
-       }
-
-       sock->packet = NULL;    /* we have no need for more partial reads */
-       request->packet = NULL;
-
-       return 1;
-}
-
-
-/*
- *     Send a response packet
- */
-int dual_tls_send(rad_listen_t *listener, REQUEST *request)
-{
-       listen_socket_t *sock = listener->data;
-
-       rad_assert(request->listener == listener);
-       rad_assert(listener->send == dual_tls_send);
-
-       /*
-        *      Accounting reject's are silently dropped.
-        *
-        *      We do it here to avoid polluting the rest of the
-        *      code with this knowledge
-        */
-       if (request->reply->code == 0) return 0;
-
-       /*
-        *      Pack the VPs
-        */
-       if (rad_encode(request->reply, request->packet,
-                      request->client->secret) < 0) {
-               RDEBUG("Failed encoding packet: %s", fr_strerror());
-               return 0;
-       }
-
-       /*
-        *      Sign the packet.
-        */
-       if (rad_sign(request->reply, request->packet,
-                      request->client->secret) < 0) {
-               RDEBUG("Failed signing packet: %s", fr_strerror());
-               return 0;
-       }
-       
-       PTHREAD_MUTEX_LOCK(&sock->mutex);
-       /*
-        *      Write the packet to the SSL buffers.
-        */
-       record_plus(&sock->ssn->clean_in,
-                   request->reply->data, request->reply->data_len);
-
-       /*
-        *      Do SSL magic to get encrypted data.
-        */
-       tls_handshake_send(request, sock->ssn);
-
-       /*
-        *      And finally write the data to the socket.
-        */
-       if (sock->ssn->dirty_out.used > 0) {
-               dump_hex("WRITE TO SSL", sock->ssn->dirty_out.data, sock->ssn->dirty_out.used);
-
-               tls_socket_write(listener, request);
-       }
-       PTHREAD_MUTEX_UNLOCK(&sock->mutex);
-
-       return 0;
-}
-
-
-int proxy_tls_recv(rad_listen_t *listener)
-{
-       int rcode;
-       size_t length;
-       listen_socket_t *sock = listener->data;
-       char buffer[256];
-       uint8_t data[1024];
-       RADIUS_PACKET *packet;
-       RAD_REQUEST_FUNP fun = NULL;
-
-       DEBUG3("Proxy SSL socket has data to read");
-       PTHREAD_MUTEX_LOCK(&sock->mutex);
-redo:
-       rcode = SSL_read(sock->ssn->ssl, data, 4);
-       if (rcode <= 0) {
-               int err = SSL_get_error(sock->ssn->ssl, rcode);
-               switch (err) {
-               case SSL_ERROR_WANT_READ:
-               case SSL_ERROR_WANT_WRITE:
-                       rcode = 0;
-                       goto redo;
-               case SSL_ERROR_ZERO_RETURN:
-                       /* remote end sent close_notify, send one back */
-                       SSL_shutdown(sock->ssn->ssl);
-
-               case SSL_ERROR_SYSCALL:
-               do_close:
-                       PTHREAD_MUTEX_UNLOCK(&sock->mutex);
-                       tls_socket_close(listener);
-                       return 0;
-
-               default:
-                       while ((err = ERR_get_error())) {
-                               DEBUG("proxy recv says %s",
-                                     ERR_error_string(err, NULL));
-                       }
-                       
-                       goto do_close;
-               }
-       }
-
-       length = (data[2] << 8) | data[3];
-       DEBUG3("Proxy received header saying we have a packet of %u bytes",
-              (unsigned int) length);
-
-       if (length > sizeof(data)) {
-               DEBUG("Received packet will be too large! (%u)",
-                     (data[2] << 8) | data[3]);
-               goto do_close;
-       }
-       
-       rcode = SSL_read(sock->ssn->ssl, data + 4, length);
-       if (rcode <= 0) {
-               switch (SSL_get_error(sock->ssn->ssl, rcode)) {
-               case SSL_ERROR_WANT_READ:
-               case SSL_ERROR_WANT_WRITE:
-                       rcode = 0;
-                       break;
-
-               case SSL_ERROR_ZERO_RETURN:
-                       /* remote end sent close_notify, send one back */
-                       SSL_shutdown(sock->ssn->ssl);
-                       goto do_close;
-               default:
-                       goto do_close;
-               }
-       }
-       PTHREAD_MUTEX_UNLOCK(&sock->mutex);
-
-       packet = rad_alloc(0);
-       packet->sockfd = listener->fd;
-       packet->src_ipaddr = sock->other_ipaddr;
-       packet->src_port = sock->other_port;
-       packet->dst_ipaddr = sock->my_ipaddr;
-       packet->dst_port = sock->my_port;
-       packet->code = data[0];
-       packet->id = data[1];
-       packet->data_len = length;
-       packet->data = rad_malloc(packet->data_len);
-       memcpy(packet->data, data, packet->data_len);
-       memcpy(packet->vector, packet->data + 4, 16);
-
-       /*
-        *      FIXME: Client MIB updates?
-        */
-       switch(packet->code) {
-       case PW_AUTHENTICATION_ACK:
-       case PW_ACCESS_CHALLENGE:
-       case PW_AUTHENTICATION_REJECT:
-               fun = rad_authenticate;
-               break;
-
-#ifdef WITH_ACCOUNTING
-       case PW_ACCOUNTING_RESPONSE:
-               fun = rad_accounting;
-               break;
-#endif
-
-       default:
-               /*
-                *      FIXME: Update MIB for packet types?
-                */
-               radlog(L_ERR, "Invalid packet code %d sent to a proxy port "
-                      "from home server %s port %d - ID %d : IGNORED",
-                      packet->code,
-                      ip_ntoh(&packet->src_ipaddr, buffer, sizeof(buffer)),
-                      packet->src_port, packet->id);
-               rad_free(&packet);
-               return 0;
-       }
-
-       if (!request_proxy_reply(packet)) {
-               rad_free(&packet);
-               return 0;
-       }
-
-       return 1;
-}
-
-int proxy_tls_send(rad_listen_t *listener, REQUEST *request)
-{
-       int rcode;
-       listen_socket_t *sock = listener->data;
-
-       /*
-        *      Normal proxying calls us with the data already
-        *      encoded.  The "ping home server" code does not.  So,
-        *      if there's no packet, encode it here.
-        */
-       if (!request->proxy->data) {
-               request->proxy_listener->encode(request->proxy_listener,
-                                               request);
-       }
-
-       DEBUG3("Proxy is writing %u bytes to SSL",
-              (unsigned int) request->proxy->data_len);
-       PTHREAD_MUTEX_LOCK(&sock->mutex);
-       while ((rcode = SSL_write(sock->ssn->ssl, request->proxy->data,
-                                 request->proxy->data_len)) < 0) {
-               int err;
-               while ((err = ERR_get_error())) {
-                       DEBUG("proxy SSL_write says %s",
-                             ERR_error_string(err, NULL));
-               }
-               PTHREAD_MUTEX_UNLOCK(&sock->mutex);
-               tls_socket_close(listener);
-               return 0;
-       }
-       PTHREAD_MUTEX_UNLOCK(&sock->mutex);
-
-       return 1;
-}
-
 #endif /* WITH_TLS */
diff --git a/src/main/tls_listen.c b/src/main/tls_listen.c
new file mode 100644 (file)
index 0000000..8d83ff3
--- /dev/null
@@ -0,0 +1,621 @@
+/*
+ * tls.c
+ *
+ * Version:     $Id$
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2001  hereUare Communications, Inc. <raghud@hereuare.com>
+ * Copyright 2003  Alan DeKok <aland@freeradius.org>
+ * Copyright 2006  The FreeRADIUS server project
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/process.h>
+#include <freeradius-devel/rad_assert.h>
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#ifdef WITH_TLS
+#ifdef HAVE_OPENSSL_RAND_H
+#include <openssl/rand.h>
+#endif
+
+#ifdef HAVE_OPENSSL_OCSP_H
+#include <openssl/ocsp.h>
+#endif
+
+#ifdef HAVE_PTHREAD_H
+#define PTHREAD_MUTEX_LOCK pthread_mutex_lock
+#define PTHREAD_MUTEX_UNLOCK pthread_mutex_unlock
+#else
+#define PTHREAD_MUTEX_LOCK(_x)
+#define PTHREAD_MUTEX_UNLOCK(_x)
+#endif
+
+static void dump_hex(const char *msg, const uint8_t *data, size_t data_len)
+{
+       size_t i;
+
+       if (debug_flag < 3) return;
+
+       printf("%s %d\n", msg, (int) data_len);
+       if (data_len > 256) data_len = 256;
+
+       for (i = 0; i < data_len; i++) {
+               if ((i & 0x0f) == 0x00) printf ("%02x: ", (unsigned int) i);
+               printf("%02x ", data[i]);
+               if ((i & 0x0f) == 0x0f) printf ("\n");
+       }
+       printf("\n");
+       fflush(stdout);
+}
+
+static void tls_socket_close(rad_listen_t *listener)
+{
+       listen_socket_t *sock = listener->data;
+
+       listener->status = RAD_LISTEN_STATUS_REMOVE_FD;
+       listener->tls = NULL; /* parent owns this! */
+       
+       if (sock->parent) {
+               /*
+                *      Decrement the number of connections.
+                */
+               if (sock->parent->num_connections > 0) {
+                       sock->parent->num_connections--;
+               }
+               if (sock->client->num_connections > 0) {
+                       sock->client->num_connections--;
+               }
+       }
+       
+       /*
+        *      Tell the event handler that an FD has disappeared.
+        */
+       DEBUG("Client has closed connection");
+       event_new_fd(listener);
+       
+       /*
+        *      Do NOT free the listener here.  It's in use by
+        *      a request, and will need to hang around until
+        *      all of the requests are done.
+        *
+        *      It is instead free'd in remove_from_request_hash()
+        */
+}
+
+static int tls_socket_write(rad_listen_t *listener, REQUEST *request)
+{
+       uint8_t *p;
+       ssize_t rcode;
+       listen_socket_t *sock = listener->data;
+
+       p = sock->ssn->dirty_out.data;
+       
+       while (p < (sock->ssn->dirty_out.data + sock->ssn->dirty_out.used)) {
+               RDEBUG3("Writing to socket %d", request->packet->sockfd);
+               rcode = write(request->packet->sockfd, p,
+                             (sock->ssn->dirty_out.data + sock->ssn->dirty_out.used) - p);
+               if (rcode <= 0) {
+                       RDEBUG("Error writing to TLS socket: %s", strerror(errno));
+                       
+                       tls_socket_close(listener);
+                       return 0;
+               }
+               p += rcode;
+       }
+
+       sock->ssn->dirty_out.used = 0;
+       
+       return 1;
+}
+
+
+static int tls_socket_recv(rad_listen_t *listener)
+{
+       int doing_init = FALSE;
+       ssize_t rcode;
+       RADIUS_PACKET *packet;
+       REQUEST *request;
+       listen_socket_t *sock = listener->data;
+       fr_tls_status_t status;
+       RADCLIENT *client = sock->client;
+
+       if (!sock->packet) {
+               sock->packet = rad_alloc(0);
+               if (!sock->packet) return 0;
+
+               sock->packet->sockfd = listener->fd;
+               sock->packet->src_ipaddr = sock->other_ipaddr;
+               sock->packet->src_port = sock->other_port;
+               sock->packet->dst_ipaddr = sock->my_ipaddr;
+               sock->packet->dst_port = sock->my_port;
+
+               if (sock->request) sock->request->packet = sock->packet;
+       }
+
+       /*
+        *      Allocate a REQUEST for debugging.
+        */
+       if (!sock->request) {
+               sock->request = request = request_alloc();
+               if (!sock->request) {
+                       radlog(L_ERR, "Out of memory");
+                       return 0;
+               }
+
+               rad_assert(request->packet == NULL);
+               rad_assert(sock->packet != NULL);
+               request->packet = sock->packet;
+
+               request->component = "<core>";
+               request->component = "<tls-connect>";
+
+               /*
+                *      Not sure if we should do this on every packet...
+                */
+               request->reply = rad_alloc(0);
+               if (!request->reply) return 0;
+
+               request->options = RAD_REQUEST_OPTION_DEBUG2;
+
+               rad_assert(sock->ssn == NULL);
+
+               sock->ssn = tls_new_session(listener->tls, sock->request,
+                                           listener->tls->require_client_cert);
+               if (!sock->ssn) {
+                       request_free(&sock->request);
+                       sock->packet = NULL;
+                       return 0;
+               }
+
+               SSL_set_ex_data(sock->ssn->ssl, FR_TLS_EX_INDEX_REQUEST, (void *)request);
+               SSL_set_ex_data(sock->ssn->ssl, FR_TLS_EX_INDEX_CERTS, (void *)&request->packet->vps);
+
+               doing_init = TRUE;
+       }
+
+       rad_assert(sock->request != NULL);
+       rad_assert(sock->request->packet != NULL);
+       rad_assert(sock->packet != NULL);
+       rad_assert(sock->ssn != NULL);
+
+       request = sock->request;
+
+       RDEBUG3("Reading from socket %d", request->packet->sockfd);
+       PTHREAD_MUTEX_LOCK(&sock->mutex);
+       rcode = read(request->packet->sockfd,
+                    sock->ssn->dirty_in.data,
+                    sizeof(sock->ssn->dirty_in.data));
+       if ((rcode < 0) && (errno == ECONNRESET)) {
+       do_close:
+               PTHREAD_MUTEX_UNLOCK(&sock->mutex);
+               tls_socket_close(listener);
+               return 0;
+       }
+       
+       if (rcode < 0) {
+               RDEBUG("Error reading TLS socket: %s", strerror(errno));
+               goto do_close;
+       }
+
+       /*
+        *      Normal socket close.
+        */
+       if (rcode == 0) goto do_close;
+       
+       sock->ssn->dirty_in.used = rcode;
+       memset(sock->ssn->dirty_in.data + sock->ssn->dirty_in.used,
+              0, 16);
+
+       dump_hex("READ FROM SSL", sock->ssn->dirty_in.data, sock->ssn->dirty_in.used);
+
+       /*
+        *      Catch attempts to use non-SSL.
+        */
+       if (doing_init && (sock->ssn->dirty_in.data[0] != handshake)) {
+               RDEBUG("Non-TLS data sent to TLS socket: closing");
+               goto do_close;
+       }
+       
+       /*
+        *      Skip ahead to reading application data.
+        */
+       if (SSL_is_init_finished(sock->ssn->ssl)) goto app;
+
+       if (!tls_handshake_recv(request, sock->ssn)) {
+               RDEBUG("FAILED in TLS handshake receive");
+               goto do_close;
+       }
+       
+       if (sock->ssn->dirty_out.used > 0) {
+               tls_socket_write(listener, request);
+               PTHREAD_MUTEX_UNLOCK(&sock->mutex);
+               return 0;
+       }
+
+app:
+       /*
+        *      FIXME: Run the packet through a virtual server in
+        *      order to see if we like the certificate presented by
+        *      the client.
+        */
+
+       status = tls_application_data(sock->ssn, request);
+       RDEBUG("Application data status %d", status);
+
+       if (status == FR_TLS_MORE_FRAGMENTS) {
+               PTHREAD_MUTEX_UNLOCK(&sock->mutex);
+               return 0;
+       }
+
+       if (sock->ssn->clean_out.used == 0) {
+               PTHREAD_MUTEX_UNLOCK(&sock->mutex);
+               return 0;
+       }
+
+       dump_hex("TUNNELED DATA", sock->ssn->clean_out.data, sock->ssn->clean_out.used);
+
+       /*
+        *      If the packet is a complete RADIUS packet, return it to
+        *      the caller.  Otherwise...
+        */
+       if ((sock->ssn->clean_out.used < 20) ||
+           (((sock->ssn->clean_out.data[2] << 8) | sock->ssn->clean_out.data[3]) != (int) sock->ssn->clean_out.used)) {
+               RDEBUG("Received bad packet: Length %d contents %d",
+                      sock->ssn->clean_out.used,
+                      (sock->ssn->clean_out.data[2] << 8) | sock->ssn->clean_out.data[3]);
+               goto do_close;
+       }
+
+       packet = sock->packet;
+       packet->data = rad_malloc(sock->ssn->clean_out.used);
+       packet->data_len = sock->ssn->clean_out.used;
+       sock->ssn->record_minus(&sock->ssn->clean_out, packet->data, packet->data_len);
+       packet->vps = NULL;
+       PTHREAD_MUTEX_UNLOCK(&sock->mutex);
+
+       if (!rad_packet_ok(packet, 0)) {
+               RDEBUG("Received bad packet: %s", fr_strerror());
+               tls_socket_close(listener);
+               return 0;       /* do_close unlocks the mutex */
+       }
+
+       /*
+        *      Copied from src/lib/radius.c, rad_recv();
+        */
+       if (fr_debug_flag) {
+               char host_ipaddr[128];
+
+               if ((packet->code > 0) && (packet->code < FR_MAX_PACKET_CODE)) {
+                       RDEBUG("tls_recv: %s packet from host %s port %d, id=%d, length=%d",
+                              fr_packet_codes[packet->code],
+                              inet_ntop(packet->src_ipaddr.af,
+                                        &packet->src_ipaddr.ipaddr,
+                                        host_ipaddr, sizeof(host_ipaddr)),
+                              packet->src_port,
+                              packet->id, (int) packet->data_len);
+               } else {
+                       RDEBUG("tls_recv: Packet from host %s port %d code=%d, id=%d, length=%d",
+                              inet_ntop(packet->src_ipaddr.af,
+                                        &packet->src_ipaddr.ipaddr,
+                                        host_ipaddr, sizeof(host_ipaddr)),
+                              packet->src_port,
+                              packet->code,
+                              packet->id, (int) packet->data_len);
+               }
+       }
+
+       FR_STATS_INC(auth, total_requests);
+
+       return 1;
+}
+
+
+int dual_tls_recv(rad_listen_t *listener)
+{
+       RADIUS_PACKET *packet;
+       REQUEST *request;
+       RAD_REQUEST_FUNP fun = NULL;
+       listen_socket_t *sock = listener->data;
+       RADCLIENT       *client = sock->client;
+
+       if (!tls_socket_recv(listener)) {
+               return 0;
+       }
+
+       rad_assert(sock->request != NULL);
+       rad_assert(sock->request->packet != NULL);
+       rad_assert(sock->packet != NULL);
+       rad_assert(sock->ssn != NULL);
+
+       request = sock->request;
+       packet = sock->packet;
+
+       /*
+        *      Some sanity checks, based on the packet code.
+        */
+       switch(packet->code) {
+       case PW_AUTHENTICATION_REQUEST:
+               if (listener->type != RAD_LISTEN_AUTH) goto bad_packet;
+               FR_STATS_INC(auth, total_requests);
+               fun = rad_authenticate;
+               break;
+
+       case PW_ACCOUNTING_REQUEST:
+               if (listener->type != RAD_LISTEN_ACCT) goto bad_packet;
+               FR_STATS_INC(acct, total_requests);
+               fun = rad_accounting;
+               break;
+
+       case PW_STATUS_SERVER:
+               if (!mainconfig.status_server) {
+                       FR_STATS_INC(auth, total_unknown_types);
+                       DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
+                       rad_free(&sock->packet);
+                       request->packet = NULL;
+                       return 0;
+               }
+               fun = rad_status_server;
+               break;
+
+       default:
+       bad_packet:
+               FR_STATS_INC(auth, total_unknown_types);
+
+               DEBUG("Invalid packet code %d sent from client %s port %d : IGNORED",
+                     packet->code, client->shortname, packet->src_port);
+               rad_free(&sock->packet);
+               request->packet = NULL;
+               return 0;
+       } /* switch over packet types */
+
+       if (!request_receive(listener, packet, client, fun)) {
+               FR_STATS_INC(auth, total_packets_dropped);
+               rad_free(&sock->packet);
+               request->packet = NULL;
+               return 0;
+       }
+
+       sock->packet = NULL;    /* we have no need for more partial reads */
+       request->packet = NULL;
+
+       return 1;
+}
+
+
+/*
+ *     Send a response packet
+ */
+int dual_tls_send(rad_listen_t *listener, REQUEST *request)
+{
+       listen_socket_t *sock = listener->data;
+
+       rad_assert(request->listener == listener);
+       rad_assert(listener->send == dual_tls_send);
+
+       /*
+        *      Accounting reject's are silently dropped.
+        *
+        *      We do it here to avoid polluting the rest of the
+        *      code with this knowledge
+        */
+       if (request->reply->code == 0) return 0;
+
+       /*
+        *      Pack the VPs
+        */
+       if (rad_encode(request->reply, request->packet,
+                      request->client->secret) < 0) {
+               RDEBUG("Failed encoding packet: %s", fr_strerror());
+               return 0;
+       }
+
+       /*
+        *      Sign the packet.
+        */
+       if (rad_sign(request->reply, request->packet,
+                      request->client->secret) < 0) {
+               RDEBUG("Failed signing packet: %s", fr_strerror());
+               return 0;
+       }
+       
+       PTHREAD_MUTEX_LOCK(&sock->mutex);
+       /*
+        *      Write the packet to the SSL buffers.
+        */
+       sock->ssn->record_plus(&sock->ssn->clean_in,
+                              request->reply->data, request->reply->data_len);
+
+       /*
+        *      Do SSL magic to get encrypted data.
+        */
+       tls_handshake_send(request, sock->ssn);
+
+       /*
+        *      And finally write the data to the socket.
+        */
+       if (sock->ssn->dirty_out.used > 0) {
+               dump_hex("WRITE TO SSL", sock->ssn->dirty_out.data, sock->ssn->dirty_out.used);
+
+               tls_socket_write(listener, request);
+       }
+       PTHREAD_MUTEX_UNLOCK(&sock->mutex);
+
+       return 0;
+}
+
+
+int proxy_tls_recv(rad_listen_t *listener)
+{
+       int rcode;
+       size_t length;
+       listen_socket_t *sock = listener->data;
+       char buffer[256];
+       uint8_t data[1024];
+       RADIUS_PACKET *packet;
+       RAD_REQUEST_FUNP fun = NULL;
+
+       DEBUG3("Proxy SSL socket has data to read");
+       PTHREAD_MUTEX_LOCK(&sock->mutex);
+redo:
+       rcode = SSL_read(sock->ssn->ssl, data, 4);
+       if (rcode <= 0) {
+               int err = SSL_get_error(sock->ssn->ssl, rcode);
+               switch (err) {
+               case SSL_ERROR_WANT_READ:
+               case SSL_ERROR_WANT_WRITE:
+                       rcode = 0;
+                       goto redo;
+               case SSL_ERROR_ZERO_RETURN:
+                       /* remote end sent close_notify, send one back */
+                       SSL_shutdown(sock->ssn->ssl);
+
+               case SSL_ERROR_SYSCALL:
+               do_close:
+                       PTHREAD_MUTEX_UNLOCK(&sock->mutex);
+                       tls_socket_close(listener);
+                       return 0;
+
+               default:
+                       while ((err = ERR_get_error())) {
+                               DEBUG("proxy recv says %s",
+                                     ERR_error_string(err, NULL));
+                       }
+                       
+                       goto do_close;
+               }
+       }
+
+       length = (data[2] << 8) | data[3];
+       DEBUG3("Proxy received header saying we have a packet of %u bytes",
+              (unsigned int) length);
+
+       if (length > sizeof(data)) {
+               DEBUG("Received packet will be too large! (%u)",
+                     (data[2] << 8) | data[3]);
+               goto do_close;
+       }
+       
+       rcode = SSL_read(sock->ssn->ssl, data + 4, length);
+       if (rcode <= 0) {
+               switch (SSL_get_error(sock->ssn->ssl, rcode)) {
+               case SSL_ERROR_WANT_READ:
+               case SSL_ERROR_WANT_WRITE:
+                       rcode = 0;
+                       break;
+
+               case SSL_ERROR_ZERO_RETURN:
+                       /* remote end sent close_notify, send one back */
+                       SSL_shutdown(sock->ssn->ssl);
+                       goto do_close;
+               default:
+                       goto do_close;
+               }
+       }
+       PTHREAD_MUTEX_UNLOCK(&sock->mutex);
+
+       packet = rad_alloc(0);
+       packet->sockfd = listener->fd;
+       packet->src_ipaddr = sock->other_ipaddr;
+       packet->src_port = sock->other_port;
+       packet->dst_ipaddr = sock->my_ipaddr;
+       packet->dst_port = sock->my_port;
+       packet->code = data[0];
+       packet->id = data[1];
+       packet->data_len = length;
+       packet->data = rad_malloc(packet->data_len);
+       memcpy(packet->data, data, packet->data_len);
+       memcpy(packet->vector, packet->data + 4, 16);
+
+       /*
+        *      FIXME: Client MIB updates?
+        */
+       switch(packet->code) {
+       case PW_AUTHENTICATION_ACK:
+       case PW_ACCESS_CHALLENGE:
+       case PW_AUTHENTICATION_REJECT:
+               fun = rad_authenticate;
+               break;
+
+#ifdef WITH_ACCOUNTING
+       case PW_ACCOUNTING_RESPONSE:
+               fun = rad_accounting;
+               break;
+#endif
+
+       default:
+               /*
+                *      FIXME: Update MIB for packet types?
+                */
+               radlog(L_ERR, "Invalid packet code %d sent to a proxy port "
+                      "from home server %s port %d - ID %d : IGNORED",
+                      packet->code,
+                      ip_ntoh(&packet->src_ipaddr, buffer, sizeof(buffer)),
+                      packet->src_port, packet->id);
+               rad_free(&packet);
+               return 0;
+       }
+
+       if (!request_proxy_reply(packet)) {
+               rad_free(&packet);
+               return 0;
+       }
+
+       return 1;
+}
+
+int proxy_tls_send(rad_listen_t *listener, REQUEST *request)
+{
+       int rcode;
+       listen_socket_t *sock = listener->data;
+
+       /*
+        *      Normal proxying calls us with the data already
+        *      encoded.  The "ping home server" code does not.  So,
+        *      if there's no packet, encode it here.
+        */
+       if (!request->proxy->data) {
+               request->proxy_listener->encode(request->proxy_listener,
+                                               request);
+       }
+
+       DEBUG3("Proxy is writing %u bytes to SSL",
+              (unsigned int) request->proxy->data_len);
+       PTHREAD_MUTEX_LOCK(&sock->mutex);
+       while ((rcode = SSL_write(sock->ssn->ssl, request->proxy->data,
+                                 request->proxy->data_len)) < 0) {
+               int err;
+               while ((err = ERR_get_error())) {
+                       DEBUG("proxy SSL_write says %s",
+                             ERR_error_string(err, NULL));
+               }
+               PTHREAD_MUTEX_UNLOCK(&sock->mutex);
+               tls_socket_close(listener);
+               return 0;
+       }
+       PTHREAD_MUTEX_UNLOCK(&sock->mutex);
+
+       return 1;
+}
+
+#endif /* WITH_TLS */
index 94ee443..e6a1a26 100644 (file)
@@ -437,7 +437,7 @@ REQUEST *request_alloc_fake(REQUEST *request)
    */
   fake->server = request->server;
 
-  fake->packet = rad_alloc(0);
+  fake->packet = rad_alloc(1);
   if (!fake->packet) {
          request_free(&fake);
          return NULL;
diff --git a/src/modules/all.mk b/src/modules/all.mk
new file mode 100644 (file)
index 0000000..fb41496
--- /dev/null
@@ -0,0 +1 @@
+SUBMAKEFILES := $(wildcard ${top_srcdir}/src/modules/rlm_*/all.mk)
diff --git a/src/modules/rlm_acct_unique/all.mk b/src/modules/rlm_acct_unique/all.mk
new file mode 100644 (file)
index 0000000..08a6a41
--- /dev/null
@@ -0,0 +1,3 @@
+SOURCES                := rlm_acct_unique.c
+
+TARGET         := rlm_acct_unique.a
diff --git a/src/modules/rlm_acctlog/all.mk b/src/modules/rlm_acctlog/all.mk
new file mode 100644 (file)
index 0000000..84fad35
--- /dev/null
@@ -0,0 +1,3 @@
+TARGET      := rlm_acctlog.a
+
+SOURCES     := rlm_acctlog.c
diff --git a/src/modules/rlm_always/all.mk b/src/modules/rlm_always/all.mk
new file mode 100644 (file)
index 0000000..8fa6663
--- /dev/null
@@ -0,0 +1,3 @@
+TARGET         := rlm_always.a
+
+SOURCES                := rlm_always.c
diff --git a/src/modules/rlm_attr_filter/all.mk b/src/modules/rlm_attr_filter/all.mk
new file mode 100644 (file)
index 0000000..6eb4442
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET         = rlm_attr_filter.a
+SOURCES                = rlm_attr_filter.c
diff --git a/src/modules/rlm_attr_rewrite/all.mk b/src/modules/rlm_attr_rewrite/all.mk
new file mode 100644 (file)
index 0000000..17c6e9c
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET      = rlm_attr_rewrite.a
+SOURCES        = rlm_attr_rewrite.c
diff --git a/src/modules/rlm_chap/all.mk b/src/modules/rlm_chap/all.mk
new file mode 100644 (file)
index 0000000..19b0d95
--- /dev/null
@@ -0,0 +1,3 @@
+SOURCES := rlm_chap.c
+
+TARGET := rlm_chap.a
diff --git a/src/modules/rlm_checkval/all.mk b/src/modules/rlm_checkval/all.mk
new file mode 100644 (file)
index 0000000..f66d692
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET      = rlm_checkval.a
+SOURCES        = rlm_checkval.c
diff --git a/src/modules/rlm_copy_packet/all.mk b/src/modules/rlm_copy_packet/all.mk
new file mode 100644 (file)
index 0000000..0223986
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET         = rlm_copy_packet.a
+SOURCES                = rlm_copy_packet.c
diff --git a/src/modules/rlm_counter/all.mk b/src/modules/rlm_counter/all.mk
new file mode 100644 (file)
index 0000000..ded5427
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET      = 
+SOURCES        = rlm_counter.c
diff --git a/src/modules/rlm_cram/all.mk b/src/modules/rlm_cram/all.mk
new file mode 100644 (file)
index 0000000..15998f0
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET         = rlm_cram.a
+SOURCES                = rlm_cram.c
index 855b284..491b1d8 100644 (file)
@@ -22,4 +22,4 @@ rlm_dbm_cat: rlm_dbm_cat.lo $(LIBRADIUS)
 
 rlm_dbm_install: rlm_dbm_cat rlm_dbm_parser
        $(INSTALL) -m 644 rlm_dbm_cat.8 $(R)$(mandir)/man8
-       $(INSTALL) -m 644 rlm_dbm_parse.8 $(R)$(mandir)/man8
+       $(INSTALL) -m 644 rlm_dbm_parser.8 $(R)$(mandir)/man8
diff --git a/src/modules/rlm_dbm/all.mk b/src/modules/rlm_dbm/all.mk
new file mode 100644 (file)
index 0000000..c37bc82
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET      = 
+SOURCES        = rlm_dbm.c
similarity index 91%
rename from src/modules/rlm_dbm/rlm_dbm_parse.8
rename to src/modules/rlm_dbm/rlm_dbm_parser.8
index 51dd1fc..578e718 100644 (file)
@@ -1,8 +1,8 @@
-.TH RLM_DBM_PARSE 8
+.TH RLM_DBM_PARSER 8
 .SH NAME
-rlm_dbm_parse - transforms simple syntax into rlm_dbm format
+rlm_dbm_parser - transforms simple syntax into rlm_dbm format
 .SH SYNOPSIS
-.B rlm_dbm_parse
+.B rlm_dbm_parser
 .RB [ \-c ]
 .RB [ \-d
 .IR raddb ]
@@ -12,17 +12,17 @@ rlm_dbm_parse - transforms simple syntax into rlm_dbm format
 .IR outputfile ]
 .RB [ \-x ]
 .RB [ \-v ]
-.RB [ \-q ] 
+.RB [ \-q ]
 [\fIusername ...\fP]
 
 .SH DESCRIPTION
-\fBrlm_dbm_parse\fP reads a file of the syntax defined below, and writes
+\fBrlm_dbm_parser\fP reads a file of the syntax defined below, and writes
 a database file usable by rlm_dbm or edits current database.
 .PP
 
 .SH INPUT FORMAT
 
-\fIrlm_dbm_parse\fP reads a format similar to the one used by the files
+\fIrlm_dbm_parser\fP reads a format similar to the one used by the files
 module. In incomplete RFC2234 ABNF, it looks like this:
 
 .nf
diff --git a/src/modules/rlm_detail/all.mk b/src/modules/rlm_detail/all.mk
new file mode 100644 (file)
index 0000000..01227d8
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET = rlm_detail.a
+SOURCES        = rlm_detail.c
index 97fd5e4..81b5352 100644 (file)
@@ -36,6 +36,14 @@ RCSID("$Id$")
 #include       <fnmatch.h>
 #endif
 
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+
 #define        DIRLEN  8192
 
 struct detail_instance {
@@ -45,6 +53,9 @@ struct detail_instance {
        /* detail file permissions */
        int detailperm;
 
+       /* detail file group */
+       char *group;
+
        /* directory permissions */
        int dirperm;
 
@@ -67,6 +78,8 @@ static const CONF_PARSER module_config[] = {
          offsetof(struct detail_instance,header), NULL, "%t" },
        { "detailperm",    PW_TYPE_INTEGER,
          offsetof(struct detail_instance,detailperm), NULL, "0600" },
+       { "group",         PW_TYPE_STRING_PTR,
+         offsetof(struct detail_instance,group), NULL,  NULL},
        { "dirperm",       PW_TYPE_INTEGER,
          offsetof(struct detail_instance,dirperm),    NULL, "0755" },
        { "locking",       PW_TYPE_BOOLEAN,
@@ -185,6 +198,12 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
        off_t           fsize;
        FILE            *fp;
 
+#ifdef HAVE_GRP_H
+       gid_t           gid;
+       struct group    *grp;
+       char            *endptr;
+#endif
+
        struct detail_instance *inst = instance;
 
        rad_assert(request != NULL);
@@ -317,6 +336,27 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
                return RLM_MODULE_FAIL;
        }
 
+
+#ifdef HAVE_GRP_H
+       if (inst->group != NULL) {
+               gid = strtol(inst->group, &endptr, 10);
+               if (*endptr != '\0') {
+                       grp = getgrnam(inst->group);
+                       if (grp == NULL) {
+                               RDEBUG2("rlm_detail: Unable to find system group \"%s\"", inst->group);
+                               goto skip_group;
+                       }
+                       gid = grp->gr_gid;
+               }
+
+               if (chown(buffer, -1, gid) == -1) {
+                       RDEBUG2("rlm_detail: Unable to change system group of \"%s\"", buffer);
+               }
+       }
+
+ skip_group:
+#endif
+
        /*
         *      Post a timestamp
         */
diff --git a/src/modules/rlm_digest/all.mk b/src/modules/rlm_digest/all.mk
new file mode 100644 (file)
index 0000000..9bf0567
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET         = rlm_digest.a
+SOURCES                = rlm_digest.c
diff --git a/src/modules/rlm_dynamic_clients/all.mk b/src/modules/rlm_dynamic_clients/all.mk
new file mode 100644 (file)
index 0000000..b4e7f50
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET         = rlm_dynamic_clients.a
+SOURCES                = rlm_dynamic_clients.c
index 7475ec8..5ea4ad5 100644 (file)
@@ -5,7 +5,7 @@
 TARGET      = @targetname@
 SRCS        = rlm_eap.c eap.c mem.c
 HEADERS     = eap.h rlm_eap.h
-RLM_CFLAGS  = $(INCLTDL) -Ilibeap
+RLM_CFLAGS  = -Ilibeap
 CLIENTLIBS  = libeap/$(LIBPREFIX)freeradius-eap.la $(LIBRADIUS)
 RLM_LIBS    = libeap/$(LIBPREFIX)freeradius-eap.la $(LIBLTDL)
 RLM_INSTALL = install-subdirs
@@ -29,7 +29,12 @@ all: common
 
 $(LT_OBJS): $(HEADERS)
 
-radeapclient: radeapclient.lo $(CLIENTLIBS)
+## this uses the RLM_CFLAGS and RLM_LIBS and SRCS defs to make TARGET.
+# This needs to be before the radeapclient rule, as the lhs $(EXEECT)
+# expansion is done as soon as the Makefile is loaded
+include ../rules.mak
+
+radeapclient$(EXEEXT): radeapclient.lo $(CLIENTLIBS)
        $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(RLM_LDFLAGS) -o radeapclient radeapclient.lo $(LIBRADIUS) $(CLIENTLIBS) $(LIBS) $(OPENSSL_LIBS)
 
 radeapclient.lo: radeapclient.c $(HEADERS)
@@ -49,6 +54,3 @@ $(RLM_SUBDIRS):
        @$(MAKE) $(MFLAGS) X=$(X)rlm_eap/ -C $@ $(WHAT_TO_MAKE)
 
 libeap/$(LIBPREFIX)freeradius-eap.la: libeap
-
-## this uses the RLM_CFLAGS and RLM_LIBS and SRCS defs to make TARGET.
-include ../rules.mak
diff --git a/src/modules/rlm_eap/all.mk b/src/modules/rlm_eap/all.mk
new file mode 100644 (file)
index 0000000..f2cb44b
--- /dev/null
@@ -0,0 +1 @@
+SUBMAKEFILES := libeap/all.mk rlm_eap.mk types/all.mk radeapclient.mk
diff --git a/src/modules/rlm_eap/libeap/all.mk b/src/modules/rlm_eap/libeap/all.mk
new file mode 100644 (file)
index 0000000..ff48e67
--- /dev/null
@@ -0,0 +1,10 @@
+TARGET := libfreeradius-eap.a
+
+SOURCES        := eapcommon.c eapcrypto.c eapsimlib.c fips186prf.c
+ifneq (${OPENSSL_LIBS},)
+SOURCES                += eap_tls.c mppe_keys.c
+endif
+
+SRC_CFLAGS     := -DEAPLIB $(OPENSSL_INCLUDE)
+
+SRC_INCDIRS    := . ..
index aac473a..c494d50 100644 (file)
@@ -110,6 +110,14 @@ typedef struct eap_packet_t {
        uint8_t         data[1];
 } eap_packet_t;
 
+/*
+ * Structure to represent eap channel binding packet format *on wire*
+ */
+typedef struct eap_chbind_packet_t {
+       uint8_t         code;
+       uint8_t         data[1];
+} eap_chbind_packet_t;
+
 
 /*
  * interfaces in eapcommon.c
@@ -120,5 +128,7 @@ extern int eap_wireformat(EAP_PACKET *reply);
 extern int eap_basic_compose(RADIUS_PACKET *packet, EAP_PACKET *reply);
 extern VALUE_PAIR *eap_packet2vp(const eap_packet_t *reply);
 extern eap_packet_t *eap_vp2packet(VALUE_PAIR *vps);
+extern VALUE_PAIR *eap_chbind_packet2vp(const eap_chbind_packet_t *packet, size_t len);
+extern size_t eap_chbind_vp2packet(VALUE_PAIR *vps, eap_chbind_packet_t **packet);
 
 #endif /* _EAP_TYPES_H */
index 889341b..4a7990b 100644 (file)
@@ -431,3 +431,102 @@ eap_packet_t *eap_vp2packet(VALUE_PAIR *vps)
 
        return eap_packet;
 }
+
+VALUE_PAIR *eap_chbind_packet2vp(const eap_chbind_packet_t *packet, size_t len)
+{
+       size_t          size;
+       const uint8_t   *ptr;
+       VALUE_PAIR      *head = NULL;
+       VALUE_PAIR      **tail = &head;
+       VALUE_PAIR      *vp;
+
+       ptr = (const uint8_t *) packet;
+
+       do {
+               size = len;
+               if (size > 247) size = 247;
+
+               vp = paircreate(PW_VENDOR_SPECIFIC, VENDORPEC_UKERNA,
+                               PW_TYPE_OCTETS);
+               if (!vp) {
+                       pairfree(&head);
+                       return NULL;
+               }
+               vp->vp_octets[0] = PW_UKERNA_CHBIND;
+               vp->vp_octets[1] = size;
+               memcpy(&vp->vp_octets[2], ptr, size);
+               vp->length = size + 2;
+
+               *tail = vp;
+               tail = &(vp->next);
+
+               ptr += size;
+               len -= size;
+       } while (len > 0);
+
+       return head;
+}
+
+
+/*
+ * Find the next EAP-CHANNEL-BINDING message in the 
+ * pair list
+ */
+static VALUE_PAIR *eap_chbind_find_pair(VALUE_PAIR *vps)
+{
+       VALUE_PAIR *result = pairfind(vps, PW_VENDOR_SPECIFIC, 
+                                     VENDORPEC_UKERNA);
+        while (result && (result->vp_octets[0] != PW_UKERNA_CHBIND))
+               result = result->next;
+       return result;
+}
+
+/*
+ * Handles multiple EAP-channel-binding Message attrs
+ * ie concatenates all to get the complete EAP-channel-binding packet.
+ */
+size_t eap_chbind_vp2packet(VALUE_PAIR *vps, eap_chbind_packet_t **result)
+{
+       VALUE_PAIR *first, *vp;
+       eap_chbind_packet_t *eap_chbind_packet;
+       unsigned char *ptr;
+       size_t len;
+
+       first = eap_chbind_find_pair(vps);
+
+       /*
+        *      Sanity check the length, BEFORE malloc'ing memory.
+        */
+       len = 0;
+       for (vp = first; vp; vp = eap_chbind_find_pair(vp)) {
+               if ((vp->length < 2) ||
+                   (vp->length != vp->vp_octets[1]+2)) {
+                       DEBUG("rlm_eap: Malformed EAP channel binding value pair.  Length in pair header does not match actual length");
+                       return 0;
+               }
+               len += vp->vp_octets[1];
+       }
+
+       /*
+        *      Now that we know the lengths are OK, allocate memory.
+        */
+       eap_chbind_packet = (eap_chbind_packet_t *) malloc(len);
+       if (eap_chbind_packet == NULL) {
+               radlog(L_ERR, "rlm_eap: out of memory");
+               return 0;
+       }
+
+       /*
+        *      Copy the data from EAP-Message's over to our EAP packet.
+        */
+       ptr = (unsigned char *)eap_chbind_packet;
+
+       /* RADIUS ensures order of attrs, so just concatenate all */
+       for (vp = first; vp; vp = eap_chbind_find_pair(vp->next)) {
+               memcpy(ptr, vp->vp_octets+2, vp->length-2);
+               ptr += vp->length-2;
+       }
+
+       *result = eap_chbind_packet;
+       return len;
+}
index 400fa37..0806f89 100644 (file)
@@ -57,11 +57,6 @@ const char *progname = "radeapclient";
 
 #ifdef WITH_TLS
 #include <freeradius-devel/tls.h>
-
-int tls_success(UNUSED tls_session_t *ssn, UNUSED REQUEST *request){return 0;}
-void tls_fail(UNUSED tls_session_t *ssn){_exit(1);}
-fr_tls_status_t tls_ack_handler(UNUSED tls_session_t *tls_session, UNUSED REQUEST *request){return FR_TLS_INVALID;}
-fr_tls_status_t tls_application_data(UNUSED tls_session_t *ssn, UNUSED REQUEST *request){return FR_TLS_INVALID;}
 #endif
 
 radlog_dest_t radlog_dest = RADLOG_STDERR;
diff --git a/src/modules/rlm_eap/radeapclient.mk b/src/modules/rlm_eap/radeapclient.mk
new file mode 100644 (file)
index 0000000..12b3003
--- /dev/null
@@ -0,0 +1,11 @@
+TARGET   := 
+SOURCES := radeapclient.c
+
+ifneq ($(OPENSSL_LIBS),)
+SOURCES += ${top_srcdir}/src/main/cb.c ${top_srcdir}/src/main/tls.c
+endif
+
+TGT_PREREQS := libfreeradius-radius.a libfreeradius-eap.a
+TGT_PRLIBS  := ${OPENSSL_LIBS} ${LIBS}
+
+SRC_INCDIRS  := libeap
diff --git a/src/modules/rlm_eap/rlm_eap.mk b/src/modules/rlm_eap/rlm_eap.mk
new file mode 100644 (file)
index 0000000..974d4bd
--- /dev/null
@@ -0,0 +1,10 @@
+TARGET := rlm_eap.a
+
+SOURCES := rlm_eap.c eap.c mem.c
+
+SRC_INCDIRS := . libeap
+
+# FIXME: This target is "phony", which means that every "make"
+# re-builds rlm_eap.  We need to re-write this to be the name
+# of the ${BUILD_DIR}/.../filename!
+#TGT_PREREQS := libfreeradius-eap.a
diff --git a/src/modules/rlm_eap/types/all.mk b/src/modules/rlm_eap/types/all.mk
new file mode 100644 (file)
index 0000000..b85d501
--- /dev/null
@@ -0,0 +1 @@
+SUBMAKEFILES := $(wildcard ${top_srcdir}/src/modules/rlm_eap/types/rlm_eap_*/all.mk)
index f766537..0faf33b 100644 (file)
@@ -6,7 +6,7 @@
 
 TARGET      = rlm_eap_gtc
 SRCS        = rlm_eap_gtc.c
-RLM_CFLAGS  = $(INCLTDL) -I../.. -I../../libeap
+RLM_CFLAGS  = -I../.. -I../../libeap
 HEADERS     =  ../../rlm_eap.h ../../eap.h
 RLM_INSTALL =
 
diff --git a/src/modules/rlm_eap/types/rlm_eap_gtc/all.mk b/src/modules/rlm_eap/types/rlm_eap_gtc/all.mk
new file mode 100644 (file)
index 0000000..519a7b3
--- /dev/null
@@ -0,0 +1,4 @@
+TARGET      := rlm_eap_gtc.a
+SOURCES     := rlm_eap_gtc.c
+
+SRC_INCDIRS := ../.. ../../libeap
index 5a57043..d74a4ea 100644 (file)
@@ -2,7 +2,7 @@ TARGET      = @targetname@
 SRCS        = logging_impl.c \
              rlm_eap_ikev2.c \
              ike_conf.c
-RLM_CFLAGS  = $(INCLTDL) -I../.. -I../../libeap $(OPENSSL_INCLUDE) @eap_ikev2_cflags@
+RLM_CFLAGS  = -I../.. -I../../libeap $(OPENSSL_INCLUDE) @eap_ikev2_cflags@
 RLM_LDFLAGS = @LDFLAGS@  @LIBS@ $(OPENSSL_LIBS)
 HEADERS     = eap_ikev2.h logging_impl.h ike_conf.h
 RLM_INSTALL = 
index 3dbf25e..43eecae 100644 (file)
@@ -6,7 +6,7 @@
 
 TARGET      = rlm_eap_leap
 SRCS        = rlm_eap_leap.c eap_leap.c smbdes.c
-RLM_CFLAGS  = $(INCLTDL) -I../.. -I../../libeap
+RLM_CFLAGS  = -I../.. -I../../libeap
 HEADERS     = eap_leap.h  ../../eap.h ../../rlm_eap.h
 RLM_INSTALL =
 
diff --git a/src/modules/rlm_eap/types/rlm_eap_leap/all.mk b/src/modules/rlm_eap/types/rlm_eap_leap/all.mk
new file mode 100644 (file)
index 0000000..d385a26
--- /dev/null
@@ -0,0 +1,4 @@
+TARGET      = rlm_eap_leap.a
+SOURCES        = rlm_eap_leap.c eap_leap.c smbdes.c
+SRC_INCDIRS  = ../.. ../../libeap
+HEADERS     = eap_leap.h  ../../eap.h ../../rlm_eap.h
index 5231e61..b7f6030 100644 (file)
@@ -7,7 +7,7 @@
 TARGET      = rlm_eap_md5
 SRCS        = rlm_eap_md5.c eap_md5.c
 HEADERS     = eap_md5.h
-RLM_CFLAGS  = $(INCLTDL) -I../.. -I../../libeap
+RLM_CFLAGS  = -I../.. -I../../libeap
 RLM_INSTALL =
 
 RLM_DIR=../../
diff --git a/src/modules/rlm_eap/types/rlm_eap_md5/all.mk b/src/modules/rlm_eap/types/rlm_eap_md5/all.mk
new file mode 100644 (file)
index 0000000..60c3ea2
--- /dev/null
@@ -0,0 +1,5 @@
+TARGET      := rlm_eap_md5.a
+SOURCES     := rlm_eap_md5.c eap_md5.c
+HEADERS     = eap_md5.h
+
+SRC_INCDIRS := ../.. ../../libeap
index bd3463d..4d4b72f 100644 (file)
@@ -7,7 +7,7 @@
 TARGET      = rlm_eap_mschapv2
 SRCS        = rlm_eap_mschapv2.c
 HEADERS     = eap_mschapv2.h
-RLM_CFLAGS  = $(INCLTDL) -I../.. -I../../libeap
+RLM_CFLAGS  = -I../.. -I../../libeap
 RLM_INSTALL =
 
 RLM_DIR=../../
diff --git a/src/modules/rlm_eap/types/rlm_eap_mschapv2/all.mk b/src/modules/rlm_eap/types/rlm_eap_mschapv2/all.mk
new file mode 100644 (file)
index 0000000..b2a91eb
--- /dev/null
@@ -0,0 +1,3 @@
+TARGET      = rlm_eap_mschapv2.a
+SOURCES      = rlm_eap_mschapv2.c
+SRC_INCDIRS  = ../.. ../../libeap
index 4f600cf..2d000e5 100644 (file)
@@ -404,7 +404,7 @@ static int mschapv2_authenticate(void *arg, EAP_HANDLER *handler)
        /*
         *      Sanity check the response.
         */
-       if (eap_ds->response->length <= 4) {
+       if (eap_ds->response->length <= 5) {
                radlog(L_ERR, "rlm_eap_mschapv2: corrupted data");
                return 0;
        }
@@ -751,7 +751,7 @@ packet_ready:
                         *      issues a re-try, we will know which
                         *      challenge value that they used.
                         */
-                       n = sscanf(response->vp_strvalue, "%*cE=%d R=%d C=%32s", &err, &retry, &buf);
+                       n = sscanf(response->vp_strvalue, "%*cE=%d R=%d C=%32s", &err, &retry, &buf[0]);
                        if (n == 3) {
                                DEBUG2("  Found new challenge from MS-CHAP-Error: err=%d retry=%d challenge=%s", err, retry, buf);
                                fr_hex2bin(buf, data->challenge, 16);
index cb5a109..c890d41 100644 (file)
@@ -5,7 +5,7 @@
 TARGET      = @targetname@
 SRCS        = rlm_eap_peap.c peap.c
 HEADERS     = eap_peap.h ../../eap.h ../../rlm_eap.h
-RLM_CFLAGS  = -I../.. -I../../libeap $(INCLTDL) $(OPENSSL_INCLUDE) @eap_peap_cflags@
+RLM_CFLAGS  = -I../.. -I../../libeap $(OPENSSL_INCLUDE) @eap_peap_cflags@
 RLM_LIBS    = @eap_peap_ldflags@ ../../libeap/$(LIBPREFIX)freeradius-eap.la $(OPENSSL_LIBS)
 RLM_INSTALL =
 
diff --git a/src/modules/rlm_eap/types/rlm_eap_peap/all.mk b/src/modules/rlm_eap/types/rlm_eap_peap/all.mk
new file mode 100644 (file)
index 0000000..d727d5c
--- /dev/null
@@ -0,0 +1,6 @@
+TARGET      = rlm_eap_peap.a
+SOURCES        = rlm_eap_peap.c peap.c
+SRC_INCDIRS  = ../.. ../../libeap
+TGT_LDLIBS = $(OPENSSL_INCLUDE) 
+TGT_LDLIBS    =  $(OPENSSL_LIBS)
+#TGT_PREREQS = libfreeradius-eap.a
index 21b7e7b..afa7da1 100644 (file)
@@ -926,7 +926,7 @@ int eappeap_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                 */
                
        case PEAP_STATUS_PHASE2_INIT: {
-               int len = t->username->length + EAP_HEADER_LEN + 1;
+               size_t len = t->username->length + EAP_HEADER_LEN + 1;
 
                t->status = PEAP_STATUS_PHASE2;
 
index 685cc3a..b30947f 100644 (file)
@@ -7,7 +7,7 @@
 TARGET      = rlm_eap_sim
 SRCS        = rlm_eap_sim.c
 HEADERS     =
-RLM_CFLAGS  = $(INCLTDL) -I../.. -I../../libeap
+RLM_CFLAGS  = -I../.. -I../../libeap
 RLM_LIBS    =  ../../libeap/$(LIBPREFIX)freeradius-eap.la
 RLM_INSTALL =
 
index 3a76a1b..41240ea 100644 (file)
@@ -5,7 +5,7 @@
 TARGET      = @targetname@
 SRCS        = rlm_eap_tls.c
 HEADERS     = rlm_eap_tls.h ../../eap.h ../../rlm_eap.h
-RLM_CFLAGS  = -I../.. -I../../libeap $(INCLTDL) $(OPENSSL_INCLUDE) @eap_tls_cflags@
+RLM_CFLAGS  = -I../.. -I../../libeap $(OPENSSL_INCLUDE) @eap_tls_cflags@
 RLM_LIBS    = @eap_tls_ldflags@ ../../libeap/$(LIBPREFIX)freeradius-eap.la $(OPENSSL_LIBS)
 RLM_INSTALL =
 
diff --git a/src/modules/rlm_eap/types/rlm_eap_tls/all.mk b/src/modules/rlm_eap/types/rlm_eap_tls/all.mk
new file mode 100644 (file)
index 0000000..5a8d688
--- /dev/null
@@ -0,0 +1,6 @@
+TARGET      = rlm_eap_tls.a
+SOURCES     = rlm_eap_tls.c
+SRC_INCDIRS  = ../.. ../../libeap 
+SRC_CFLAGS = $(OPENSSL_INCLUDE) 
+TGT_LDLIBS    =  $(OPENSSL_LIBS)
+#TGT_PREREQS  = libfreeradius-eap.a
index e5616d1..56ac645 100644 (file)
@@ -254,12 +254,11 @@ static int eaptls_initiate(void *type_arg, EAP_HANDLER *handler)
 /*
  *     Do authentication, by letting EAP-TLS do most of the work.
  */
-static int eaptls_authenticate(void *arg, EAP_HANDLER *handler)
+static int eaptls_authenticate(UNUSED void *arg, EAP_HANDLER *handler)
 {
        fr_tls_status_t status;
        tls_session_t *tls_session = (tls_session_t *) handler->opaque;
        REQUEST *request = handler->request;
-       fr_tls_server_conf_t *inst = arg;
 
        RDEBUG2("Authenticate");
 
index a53d277..c09443e 100644 (file)
@@ -5,7 +5,7 @@
 TARGET      = @targetname@
 SRCS        = rlm_eap_tnc.c eap_tnc.c tncs_connect.c 
 HEADERS     = eap_tnc.h tncs.h tncs_connect.h ../../eap.h ../../rlm_eap.h
-RLM_CFLAGS  = -I../.. -I../../libeap $(INCLTDL) $(OPENSSL_INCLUDE) @eap_tnc_cflags@
+RLM_CFLAGS  = -I../.. -I../../libeap $(OPENSSL_INCLUDE) @eap_tnc_cflags@
 RLM_LIBS    = @eap_tnc_ldflags@ ../../libeap/$(LIBPREFIX)freeradius-eap.la $(OPENSSL_LIBS)
 RLM_INSTALL =
 
index 8187fba..d76a72c 100644 (file)
@@ -5,7 +5,7 @@
 TARGET      = @targetname@
 SRCS        = rlm_eap_ttls.c ttls.c
 HEADERS     = eap_ttls.h ../../eap.h ../../rlm_eap.h
-RLM_CFLAGS  = -I../.. -I../../libeap $(INCLTDL) $(OPENSSL_INCLUDE) @eap_ttls_cflags@
+RLM_CFLAGS  = -I../.. -I../../libeap $(OPENSSL_INCLUDE) @eap_ttls_cflags@
 RLM_LIBS    = @eap_ttls_ldflags@ ../../libeap/$(LIBPREFIX)freeradius-eap.la $(OPENSSL_LIBS)
 RLM_INSTALL =
 
diff --git a/src/modules/rlm_eap/types/rlm_eap_ttls/all.mk b/src/modules/rlm_eap/types/rlm_eap_ttls/all.mk
new file mode 100644 (file)
index 0000000..c79e6f9
--- /dev/null
@@ -0,0 +1,6 @@
+TARGET      = rlm_eap_ttls.a
+SOURCES        = rlm_eap_ttls.c ttls.c
+SRC_INCDIRS  = ../.. ../../libeap
+TGT_LDLIBS = $(OPENSSL_INCLUDE) 
+TGT_LDLIBS    =  $(OPENSSL_LIBS)
+#TGT_PREREQS = libfreeradius-eap.a
index 056e415..4fd9a16 100644 (file)
@@ -954,6 +954,8 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
        const uint8_t *data;
        size_t data_len;
        REQUEST *request = handler->request;
+       eap_chbind_packet_t *chbind_packet;
+       size_t chbind_len;
 
        rad_assert(request != NULL);
 
@@ -1195,6 +1197,36 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
        }
 
        /*
+        *      Process channel binding here.
+        */
+       chbind_len = eap_chbind_vp2packet(fake->packet->vps, &chbind_packet);
+       if (chbind_len > 0) {
+               /*CHBIND_REQ *req = chbind_allocate();
+               req->chbind_req = chbind_packet;
+               req->chbind_req_len = chbind_len;
+               if (fake->username) {
+                       req->username = fake->username->vp_octets;
+                       req->username_len = fake->username->length;
+               } else {
+                       req->username = NULL;
+                       req->username_len = 0;
+               }
+               chbind_process(request, req);
+               */
+
+               /* free the chbind packet; we're done with it */
+               free(chbind_packet);
+
+               /* encapsulate response here */
+               /*pairadd(replyvps, eap_chbind_packet2vp(req->chbind_resp,
+                                                      req->chbind_resp_len));
+               */
+
+               /* clean up chbind req */
+               /*chbind_free(req);*/
+       }
+
+       /*
         *      Call authentication recursively, which will
         *      do PAP, CHAP, MS-CHAP, etc.
         */
index 4ad2b76..505b3bb 100644 (file)
@@ -20,7 +20,7 @@ HOSTAP            = /path/to/hostap
 TARGET      = 
 SRCS        = rlm_eap2.c
 HEADERS     =
-RLM_CFLAGS  = $(INCLTDL) -I$(HOSTAP)/src/eap_common \
+RLM_CFLAGS  = -I$(HOSTAP)/src/eap_common \
              -I$(HOSTAP)/src/eap_server  -I$(HOSTAP)/src  \
              -I$(HOSTAP)/src/common -I$(HOSTAP)/src/utils
 RLM_LIBS    = $(HOSTAP)/eap_example/libeap.so
diff --git a/src/modules/rlm_eap2/all.mk b/src/modules/rlm_eap2/all.mk
new file mode 100644 (file)
index 0000000..4a1c5a1
--- /dev/null
@@ -0,0 +1,3 @@
+TARGET      = 
+SOURCES        = rlm_eap2.c
+## this uses the RLM_CFLAGS and RLM_LIBS and SOURCES defs to make TARGET.
diff --git a/src/modules/rlm_exec/all.mk b/src/modules/rlm_exec/all.mk
new file mode 100644 (file)
index 0000000..60f61f3
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET         = rlm_exec.a
+SOURCES                = rlm_exec.c
diff --git a/src/modules/rlm_expiration/all.mk b/src/modules/rlm_expiration/all.mk
new file mode 100644 (file)
index 0000000..0b40eb2
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET  = rlm_expiration.a
+SOURCES    = rlm_expiration.c
diff --git a/src/modules/rlm_expr/all.mk b/src/modules/rlm_expr/all.mk
new file mode 100644 (file)
index 0000000..110867e
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET         = rlm_expr.a
+SOURCES                = rlm_expr.c paircmp.c
index 80e1f08..b98afa7 100644 (file)
@@ -258,7 +258,6 @@ static size_t rand_xlat(void *instance, REQUEST *request, char *fmt,
                        char *out, size_t outlen,
                        RADIUS_ESCAPE_STRING func)
 {
-       int             rcode;
        int64_t         result;
        rlm_expr_t      *inst = instance;
        char            buffer[256];
diff --git a/src/modules/rlm_fastusers/all.mk b/src/modules/rlm_fastusers/all.mk
new file mode 100644 (file)
index 0000000..7ca7c1e
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET = rlm_fastusers.a
+SOURCES        = rlm_fastusers.c
diff --git a/src/modules/rlm_files/all.mk b/src/modules/rlm_files/all.mk
new file mode 100644 (file)
index 0000000..c26c934
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET = rlm_files.a
+SOURCES        = rlm_files.c
index 358edc4..f8790d4 100644 (file)
@@ -14,7 +14,7 @@ include ../rules.mak
 
 $(LT_OBJS): $(HEADERS)
 
-rlm_ippool_tool: rlm_ippool_tool.lo $(LIBRADIUS)
+rlm_ippool_tool$(EXEEXT): rlm_ippool_tool.lo $(LIBRADIUS)
        $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(RLM_LDFLAGS) \
                -o $@ $^ $(RLM_LIBS) $(LIBS)
 
diff --git a/src/modules/rlm_ippool/all.mk b/src/modules/rlm_ippool/all.mk
new file mode 100644 (file)
index 0000000..847dcdd
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET      = 
+SOURCES        = rlm_ippool.c
diff --git a/src/modules/rlm_jradius/all.mk b/src/modules/rlm_jradius/all.mk
new file mode 100644 (file)
index 0000000..d7d42bd
--- /dev/null
@@ -0,0 +1,3 @@
+TARGET      = rlm_jradius.a
+SOURCES        = rlm_jradius.c 
+## this uses the RLM_CFLAGS and RLM_LIBS and SOURCES defs to make TARGET.
diff --git a/src/modules/rlm_krb5/all.mk.in b/src/modules/rlm_krb5/all.mk.in
new file mode 100644 (file)
index 0000000..791cf7b
--- /dev/null
@@ -0,0 +1,12 @@
+TARGETNAME     = @targetname@
+
+ifneq "$(TARGETNAME)" ""
+TARGET         = $(TARGETNAME).a
+endif
+
+SOURCES                = rlm_krb5.c
+
+SRC_CFLAGS     = @krb5_cflags@
+TGT_LDLIBS     = @krb5_ldflags@
+
+SRC_CFLAGS     += -I/usr/include/et -DKRB5_DEPRECATED
index bdc9c51..7bc5618 100755 (executable)
@@ -4036,7 +4036,7 @@ krb5_cflags="${krb5_h_cflags} $SMART_CFLAGS"
   unset ac_cv_env_LIBS_set
   unset ac_cv_env_LIBS_value
 
-  ac_config_files="$ac_config_files Makefile"
+  ac_config_files="$ac_config_files Makefile all.mk"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
index 2b69b37..65f2e69 100644 (file)
@@ -107,3 +107,4 @@ AC_SUBST(krb5_cflags)
 AC_SUBST(krb5_ldflags)
 AC_SUBST(targetname)
 AC_OUTPUT(Makefile)
+AC_OUTPUT(all.mk)
diff --git a/src/modules/rlm_ldap/all.mk.in b/src/modules/rlm_ldap/all.mk.in
new file mode 100644 (file)
index 0000000..2747650
--- /dev/null
@@ -0,0 +1,10 @@
+TARGETNAME     = @targetname@
+
+ifneq "$(TARGETNAME)" ""
+TARGET         = $(TARGETNAME).a
+endif
+
+SOURCES                = rlm_ldap.c @edir@
+
+SRC_CFLAGS     = @ldap_cflags@
+TGT_LDLIBS     = @ldap_ldflags@
index 8fc6c38..3bec0f3 100755 (executable)
@@ -3937,7 +3937,7 @@ ldap_cflags="$SMART_CFLAGS -DLDAP_DEPRECATED -DLDAP_SET_REBIND_PROC_ARGS=$ac_cv_
   unset ac_cv_env_LIBS_set
   unset ac_cv_env_LIBS_value
 
-  ac_config_files="$ac_config_files Makefile"
+  ac_config_files="$ac_config_files Makefile all.mk"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
index b998e76..007b3ed 100644 (file)
@@ -179,3 +179,4 @@ AC_SUBST(ldap_ldflags)
 AC_SUBST(ldap_cflags)
 AC_SUBST(targetname)
 AC_OUTPUT(Makefile)
+AC_OUTPUT(all.mk)
diff --git a/src/modules/rlm_linelog/all.mk b/src/modules/rlm_linelog/all.mk
new file mode 100644 (file)
index 0000000..bd8ae68
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET         = rlm_linelog.a
+SOURCES                = rlm_linelog.c
index 24c809f..1257555 100644 (file)
@@ -31,6 +31,14 @@ RCSID("$Id$")
 #include <fcntl.h>
 #endif
 
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+
 #ifdef HAVE_SYSLOG_H
 #include <syslog.h>
 
@@ -46,6 +54,7 @@ typedef struct rlm_linelog_t {
        CONF_SECTION    *cs;
        char            *filename;
        int             permissions;
+       char            *group;
        char            *line;
        char            *reference;
 } rlm_linelog_t;
@@ -64,6 +73,8 @@ static const CONF_PARSER module_config[] = {
          offsetof(rlm_linelog_t,filename), NULL,  NULL},
        { "permissions",  PW_TYPE_INTEGER,
          offsetof(rlm_linelog_t,permissions), NULL,  "0600"},
+       { "group",  PW_TYPE_STRING_PTR,
+         offsetof(rlm_linelog_t,group), NULL,  NULL},
        { "format",  PW_TYPE_STRING_PTR,
          offsetof(rlm_linelog_t,line), NULL,  NULL},
        { "reference",  PW_TYPE_STRING_PTR,
@@ -199,6 +210,12 @@ static int do_linelog(void *instance, REQUEST *request)
        rlm_linelog_t *inst = (rlm_linelog_t*) instance;
        const char *value = inst->line;
 
+#ifdef HAVE_GRP_H
+       gid_t gid;
+       struct group *grp;
+       char *endptr;
+#endif
+
        if (inst->reference) {
                CONF_ITEM *ci;
                CONF_PAIR *cp;
@@ -263,6 +280,26 @@ static int do_linelog(void *instance, REQUEST *request)
                }
        }
 
+#ifdef HAVE_GRP_H
+       if (inst->group != NULL) {
+               gid = strtol(inst->group, &endptr, 10);
+               if (*endptr != '\0') {
+                       grp = getgrnam(inst->group);
+                       if (grp == NULL) {
+                               RDEBUG2("Unable to find system group \"%s\"", inst->group);
+                               goto skip_group;
+                       }
+                       gid = grp->gr_gid;
+               }
+
+               if (chown(buffer, -1, gid) == -1) {
+                       RDEBUG2("Unable to change system group of \"%s\"", buffer);
+               }
+       }
+
+ skip_group:
+#endif
+
        /*
         *      FIXME: Check length.
         */
diff --git a/src/modules/rlm_logintime/all.mk b/src/modules/rlm_logintime/all.mk
new file mode 100644 (file)
index 0000000..f23b508
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET  = rlm_logintime.a
+SOURCES    = rlm_logintime.c timestr.c
index 5be6fd8..05ad940 100644 (file)
@@ -10,7 +10,7 @@ HEADERS               = mschap.h smbdes.h
 RLM_CFLAGS     =
 RLM_LDFLAGS    =
 RLM_LIBS       =
-RLM_UTILS      = smbencrypt
+RLM_UTILS      = smbencrypt$(EXEEXT)
 RLM_INSTALL = 
 
 # over-ride the previous assignment if we're not building anything
@@ -18,7 +18,7 @@ include ../rules.mak
 
 $(LT_OBJS): $(HEADERS)
 
-smbencrypt: smbencrypt.lo smbdes.lo $(LIBRADIUS)
+smbencrypt$(EXEEXT): smbencrypt.lo smbdes.lo $(LIBRADIUS)
        @echo LINK $@ $^
        @$(LIBTOOL) --quiet --mode=link $(CC) $(LDFLAGS) $(RLM_LDFLAGS) \
                -o $@ $^ $(RLM_LIBS) $(LIBS)
diff --git a/src/modules/rlm_mschap/all.mk b/src/modules/rlm_mschap/all.mk
new file mode 100644 (file)
index 0000000..ed6fb82
--- /dev/null
@@ -0,0 +1 @@
+SUBMAKEFILES := rlm_mschap.mk smbencrypt.mk
index 9490a5c..46b3fd4 100644 (file)
@@ -40,6 +40,7 @@ RCSID("$Id$")
 #include       <ctype.h>
 
 #include       "smbdes.h"
+#include       "mschap.h"
 
 /*
  *     ntpwdhash converts Unicode password to 16-byte NT hash
diff --git a/src/modules/rlm_mschap/rlm_mschap.mk b/src/modules/rlm_mschap/rlm_mschap.mk
new file mode 100644 (file)
index 0000000..9755f38
--- /dev/null
@@ -0,0 +1,4 @@
+
+SOURCES := rlm_mschap.c smbdes.c opendir.c mschap.c
+
+TARGET := rlm_mschap.a
diff --git a/src/modules/rlm_mschap/smbencrypt.mk b/src/modules/rlm_mschap/smbencrypt.mk
new file mode 100644 (file)
index 0000000..04e927b
--- /dev/null
@@ -0,0 +1,6 @@
+TGT_PREREQS := libfreeradius-radius.a
+SOURCES := smbencrypt.c smbdes.c
+
+TGT_LDLIBS := $(LIBS)
+
+TARGET := smbencrypt
diff --git a/src/modules/rlm_otp/all.mk b/src/modules/rlm_otp/all.mk
new file mode 100644 (file)
index 0000000..7fb6e63
--- /dev/null
@@ -0,0 +1,8 @@
+# TARGET should be set by autoconf only.  Don't touch it.
+# The SOURCES definition should list ALL source files.
+TARGET         = rlm_otp.a
+SOURCES           = otp_rlm.c otp_radstate.c otp_pwe.c otp_pw_valid.c
+SOURCES          += otp_util.c otp_mppe.c
+SRC_CFLAGS     =  $(OPENSSL_INCLUDE)
+TGT_LDLIBS       =  $(OPENSSL_LIBS)
+
diff --git a/src/modules/rlm_pam/all.mk.in b/src/modules/rlm_pam/all.mk.in
new file mode 100644 (file)
index 0000000..59883d4
--- /dev/null
@@ -0,0 +1,10 @@
+TARGETNAME     = @targetname@
+
+ifneq "$(TARGETNAME)" ""
+TARGET         = $(TARGETNAME).a
+endif
+
+SOURCES                = rlm_pam.c
+
+SRC_CFLAGS     = @pam_cflags@
+TGT_LDLIBS     = @pam_ldflags@
index 5098c1a..15c99a9 100755 (executable)
@@ -3546,7 +3546,7 @@ ac_config_headers="$ac_config_headers config.h"
   unset ac_cv_env_LIBS_set
   unset ac_cv_env_LIBS_value
 
-  ac_config_files="$ac_config_files Makefile"
+  ac_config_files="$ac_config_files Makefile all.mk"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
index d4572f2..8faa53e 100644 (file)
@@ -49,3 +49,4 @@ AC_SUBST(pam_cflags)
 AC_SUBST(targetname)
 AC_CONFIG_HEADER(config.h)
 AC_OUTPUT(Makefile)
+AC_OUTPUT(all.mk)
diff --git a/src/modules/rlm_pap/all.mk b/src/modules/rlm_pap/all.mk
new file mode 100644 (file)
index 0000000..714a1af
--- /dev/null
@@ -0,0 +1,3 @@
+SOURCES := rlm_pap.c
+
+TARGET := rlm_pap.a
diff --git a/src/modules/rlm_passwd/all.mk b/src/modules/rlm_passwd/all.mk
new file mode 100644 (file)
index 0000000..6e9ece5
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET     = rlm_passwd.a
+SOURCES       = rlm_passwd.c
index 806f56f..be6f064 100644 (file)
@@ -38,7 +38,6 @@ struct hashtable {
        int ignorenis;
        char * filename;
        struct mypasswd **table;
-       struct mypasswd *last_found;
        char buffer[1024];
        FILE *fp;
        char delimiter;
@@ -245,7 +244,8 @@ static struct hashtable * build_hash_table (const char * file, int nfields,
 #undef passwd
 }
 
-static struct mypasswd * get_next(char *name, struct hashtable *ht)
+static struct mypasswd * get_next(char *name, struct hashtable *ht,
+                                 struct mypasswd **last_found)
 {
 #define passwd ((struct mypasswd *) ht->buffer)
        struct mypasswd * hashentry;
@@ -255,11 +255,11 @@ static struct mypasswd * get_next(char *name, struct hashtable *ht)
 
        if (ht->tablesize > 0) {
                /* get saved address of next item to check from buffer */
-               hashentry = ht->last_found;
+               hashentry = *last_found;
                for (; hashentry; hashentry = hashentry->next) {
                        if (!strcmp(hashentry->field[ht->keyfield], name)) {
                                /* save new address */
-                               ht->last_found = hashentry->next;
+                               *last_found = hashentry->next;
                                return hashentry;
                        }
                }
@@ -291,19 +291,20 @@ static struct mypasswd * get_next(char *name, struct hashtable *ht)
 #undef passwd
 }
 
-static struct mypasswd * get_pw_nam(char * name, struct hashtable* ht)
+static struct mypasswd * get_pw_nam(char * name, struct hashtable* ht,
+                                   struct mypasswd **last_found)
 {
        int h;
        struct mypasswd * hashentry;
 
        if (!ht || !name || *name == '\0') return NULL;
-       ht->last_found = NULL;
+       *last_found = NULL;
        if (ht->tablesize > 0) {
                h = hash (name, ht->tablesize);
                for (hashentry = ht->table[h]; hashentry; hashentry = hashentry->next)
                        if (!strcmp(hashentry->field[ht->keyfield], name)){
                                /* save address of next item to check into buffer */
-                               ht->last_found=hashentry->next;
+                               *last_found=hashentry->next;
                                return hashentry;
                        }
                return NULL;
@@ -313,7 +314,7 @@ static struct mypasswd * get_pw_nam(char * name, struct hashtable* ht)
                ht->fp = NULL;
        }
        if (!(ht->fp=fopen(ht->filename, "r"))) return NULL;
-       return get_next(name, ht);
+       return get_next(name, ht, last_found);
 }
 
 #ifdef TEST
@@ -323,7 +324,7 @@ static struct mypasswd * get_pw_nam(char * name, struct hashtable* ht)
 int main(void){
  struct hashtable *ht;
  char *buffer;
- struct mypasswd* pw;
+ struct mypasswd* pw, *last_found;
  int i;
 
  ht = build_hash_table("/etc/group", 4, 3, 1, 100, 0, ":");
@@ -338,9 +339,9 @@ int main(void){
 
  while(fgets(buffer, 1024, stdin)){
   buffer[strlen(buffer)-1] = 0;
-  pw = get_pw_nam(buffer, ht);
+  pw = get_pw_nam(buffer, ht, &last_found);
   printpw(pw,4);
-  while (pw = get_next(buffer, ht)) printpw(pw,4);
+  while (pw = get_next(buffer, ht, &last_found)) printpw(pw,4);
  }
  release_ht(ht);
 }
@@ -402,12 +403,21 @@ static int passwd_instantiate(CONF_SECTION *conf, void **instance)
                return -1;
        }
        if(!inst->filename || *inst->filename == '\0' || !inst->format || *inst->format == '\0') {
-               radlog(L_ERR, "rlm_passwd: cann't find passwd file and/or format in configuration");
+               radlog(L_ERR, "rlm_passwd: can't find passwd file and/or format in configuration");
+               free(inst);
                return -1;
        }
+
+       if (inst->hashsize == 0) {
+               radlog(L_ERR, "rlm_passwd: hashsize=0 is no longer permitted as it will break the server.");
+               free(inst);
+               return -1;
+       }
+
        lf=strdup(inst->format);
        if ( lf == NULL) {
                radlog(L_ERR, "rlm_passwd: memory allocation failed for lf");
+               free(inst);
                return -1;
        }
        memset(lf, 0, strlen(inst->format));
@@ -519,7 +529,7 @@ static int passwd_map(void *instance, REQUEST *request)
 #define inst ((struct passwd_instance *)instance)
        char buffer[1024];
        VALUE_PAIR * key;
-       struct mypasswd * pw;
+       struct mypasswd * pw, *last_found;
        int found = 0;
 
        for (key = request->packet->vps;
@@ -529,14 +539,14 @@ static int passwd_map(void *instance, REQUEST *request)
                 *      Ensure we have the string form of the attribute
                 */
                vp_prints_value(buffer, sizeof(buffer), key, 0);
-               if (! (pw = get_pw_nam(buffer, inst->ht)) ) {
+               if (! (pw = get_pw_nam(buffer, inst->ht, &last_found)) ) {
                        continue;
                }
                do {
                        addresult(inst, request, &request->config_items, pw, 0, "config_items");
                        addresult(inst, request, &request->reply->vps, pw, 1, "reply_items");
                        addresult(inst, request, &request->packet->vps,         pw, 2, "request_items");
-               } while ( (pw = get_next(buffer, inst->ht)) );
+               } while ( (pw = get_next(buffer, inst->ht, &last_found)) );
                found++;
                if (!inst->allowmultiple) break;
        }
diff --git a/src/modules/rlm_perl/all.mk.in b/src/modules/rlm_perl/all.mk.in
new file mode 100644 (file)
index 0000000..f697657
--- /dev/null
@@ -0,0 +1,10 @@
+TARGETNAME     = @targetname@
+
+ifneq "$(TARGETNAME)" ""
+TARGET         = $(TARGETNAME).a
+endif
+
+SOURCES                = rlm_perl.c
+
+SRC_CFLAGS     = @perl_cflags@
+TGT_LDLIBS     = @perl_ldflags@
index bf1e0f2..71b6759 100755 (executable)
@@ -3387,7 +3387,7 @@ ac_config_headers="$ac_config_headers config.h"
   unset ac_cv_env_LIBS_set
   unset ac_cv_env_LIBS_value
 
-  ac_config_files="$ac_config_files Makefile"
+  ac_config_files="$ac_config_files Makefile all.mk"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
index 51bf9a6..3f9b5ba 100644 (file)
@@ -90,3 +90,4 @@ AC_CONFIG_HEADER(config.h)
 
 AC_SUBST(targetname)
 AC_OUTPUT(Makefile)
+AC_OUTPUT(all.mk)
diff --git a/src/modules/rlm_policy/all.mk b/src/modules/rlm_policy/all.mk
new file mode 100644 (file)
index 0000000..468f346
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET         = rlm_policy.a
+SOURCES                = rlm_policy.c parse.c evaluate.c
index 3c1a000..69650ef 100644 (file)
@@ -348,23 +348,23 @@ static int policy_stack_push(policy_state_t *state, const policy_item_t *item)
 /*
  *     Pop an item from the state.
  */
-static int policy_stack_pop(policy_state_t *state, const policy_item_t **pitem)
+static int policy_stack_pop(policy_state_t *state, const policy_item_t **item)
 {
-       rad_assert(pitem != NULL);
+       rad_assert(item != NULL);
        rad_assert(state->depth >= 0);
 
  redo:
        if (state->depth == 0) {
-               *pitem = NULL;
+               *item = NULL;
                return 0;
        }
 
-       *pitem = state->stack[state->depth - 1];
+       *item = state->stack[state->depth - 1];
 
        /*
         *      Named policies are on the stack for catching recursion.
         */
-       if ((*pitem)->type == POLICY_TYPE_NAMED_POLICY) {
+       if ((*item)->type == POLICY_TYPE_NAMED_POLICY) {
                state->depth--;
                goto redo;
        }
@@ -372,12 +372,12 @@ static int policy_stack_pop(policy_state_t *state, const policy_item_t **pitem)
        /*
         *      Process the whole item list.
         */
-       if ((*pitem)->next) {
-               state->stack[state->depth - 1] = (*pitem)->next;
-               debug_evaluate("pop/push %d %p\n", state->depth - 1, *pitem);
+       if ((*item)->next) {
+               state->stack[state->depth - 1] = (*item)->next;
+               debug_evaluate("pop/push %d %p\n", state->depth - 1, *item);
        } else {
                state->depth--;         /* points to unused entry */
-               debug_evaluate("pop %d %p\n", state->depth, *pitem);
+               debug_evaluate("pop %d %p\n", state->depth, *item);
        }
 
        return 1;
index 71a7eb6..99376c7 100644 (file)
@@ -1532,7 +1532,7 @@ static int parse_named_policy(policy_lex_file_t *lexer)
        }
 
        if ((lexer->debug & POLICY_DEBUG_PRINT_POLICY) != 0) {
-               rlm_policy_print(this);
+               rlm_policy_print((policy_item_t *) this);
        }
 
                return 1;
diff --git a/src/modules/rlm_preprocess/all.mk b/src/modules/rlm_preprocess/all.mk
new file mode 100644 (file)
index 0000000..5d9eaf8
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET = rlm_preprocess.a
+SOURCES        = rlm_preprocess.c
index 41e200e..02862e6 100644 (file)
@@ -43,6 +43,7 @@ typedef struct rlm_preprocess_t {
        int             with_specialix_jetstream_hack;
        int             with_cisco_vsa_hack;
        int             with_alvarion_vsa_hack;
+       int             with_cablelabs_vsa_hack;
 } rlm_preprocess_t;
 
 static const CONF_PARSER module_config[] = {
@@ -66,6 +67,8 @@ static const CONF_PARSER module_config[] = {
          offsetof(rlm_preprocess_t,with_cisco_vsa_hack), NULL, "no" },
        { "with_alvarion_vsa_hack",        PW_TYPE_BOOLEAN,
          offsetof(rlm_preprocess_t,with_alvarion_vsa_hack), NULL, "no" },
+       { "with_cablelabs_vsa_hack",        PW_TYPE_BOOLEAN,
+         offsetof(rlm_preprocess_t,with_cablelabs_vsa_hack), NULL, NULL },
 
        { NULL, -1, 0, NULL, NULL }
 };
@@ -201,6 +204,66 @@ static void alvarion_vsa_hack(VALUE_PAIR *vp)
 }
 
 /*
+ *     Cablelabs magic, taken from:
+ *
+ * http://www.cablelabs.com/packetcable/downloads/specs/PKT-SP-EM-I12-05812.pdf
+ *
+ *     Sample data is:
+ *
+ *     0x0001d2d2026d30310000000000003030
+ *       3130303030000e812333000100033031
+ *       00000000000030303130303030000000
+ *       00063230313230313331303630323231
+ *       2e3633390000000081000500
+ */
+
+typedef struct cl_timezone_t {
+       uint8_t         dst;
+       uint8_t         sign;
+       uint8_t         hh[2];
+       uint8_t         mm[2];
+       uint8_t         ss[2];
+} cl_timezone_t;
+
+typedef struct cl_bcid_t {
+       uint32_t        timestamp;
+       uint8_t         element_id[8];
+       cl_timezone_t   timezone;
+       uint32_t        event_counter;
+} cl_bcid_t;
+
+typedef struct cl_em_hdr_t {
+       uint16_t        version;
+       cl_bcid_t       bcid;
+       uint16_t        message_type;
+       uint16_t        element_type;
+       uint8_t         element_id[8];
+       cl_timezone_t   time_zone;
+       uint32_t        sequence_number;
+       uint8_t         event_time[18];
+       uint8_t         status[4];
+       uint8_t         priority;
+       uint16_t        attr_count; /* of normal Cablelabs VSAs */
+       uint8_t         event_object;
+} cl_em_hdr_t;
+
+
+static void cablelabs_vsa_hack(VALUE_PAIR **list)
+{
+       VALUE_PAIR *ev, *vp;
+
+       ev = pairfind(&list, 1, 4491); /* Cablelabs-Event-Message */
+       if (!ev) return;
+
+       /*
+        *      FIXME: write 100's of lines of code to decode
+        *      each data structure above.
+        */
+}
+
+
+
+/*
  *     Mangle username if needed, IN PLACE.
  */
 static void rad_mangle(rlm_preprocess_t *data, REQUEST *request)
@@ -566,6 +629,14 @@ static int preprocess_authorize(void *instance, REQUEST *request)
                alvarion_vsa_hack(request->packet->vps);
        }
 
+       if (data->with_cablelabs_vsa_hack) {
+               /*
+                *      We need to run this hack because the Cablelabs
+                *      people are crazy.
+                */
+               cablelabs_vsa_hack(&request->packet->vps);
+       }
+
        /*
         *      Note that we add the Request-Src-IP-Address to the request
         *      structure BEFORE checking huntgroup access.  This allows
@@ -635,6 +706,14 @@ static int preprocess_preaccounting(void *instance, REQUEST *request)
                alvarion_vsa_hack(request->packet->vps);
        }
 
+       if (data->with_cablelabs_vsa_hack) {
+               /*
+                *      We need to run this hack because the Cablelabs
+                *      people are crazy.
+                */
+               cablelabs_vsa_hack(&request->packet->vps);
+       }
+
        /*
         *  Ensure that we log the NAS IP Address in the packet.
         */
diff --git a/src/modules/rlm_python/all.mk.in b/src/modules/rlm_python/all.mk.in
new file mode 100644 (file)
index 0000000..19bfedc
--- /dev/null
@@ -0,0 +1,10 @@
+TARGETNAME     = @targetname@
+
+ifneq "$(TARGETNAME)" ""
+TARGET         = $(TARGETNAME).a
+endif
+
+SOURCES                = rlm_python.c
+
+TGT_LDLIBS     = @python_ldflags@
+SRC_CFLAGS     = @python_cflags@
index b670192..ee7ad7b 100755 (executable)
@@ -3388,7 +3388,7 @@ fi
   unset ac_cv_env_LIBS_set
   unset ac_cv_env_LIBS_value
 
-  ac_config_files="$ac_config_files Makefile"
+  ac_config_files="$ac_config_files Makefile all.mk"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
index 5e2106e..c72c208 100644 (file)
@@ -115,3 +115,4 @@ AC_SUBST(python_ldflags)
 AC_SUBST(python_cflags)
 AC_SUBST(targetname)
 AC_OUTPUT(Makefile)
+AC_OUTPUT(all.mk)
diff --git a/src/modules/rlm_radutmp/all.mk b/src/modules/rlm_radutmp/all.mk
new file mode 100644 (file)
index 0000000..359a532
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET     = rlm_radutmp.a
+SOURCES       = rlm_radutmp.c
diff --git a/src/modules/rlm_realm/all.mk b/src/modules/rlm_realm/all.mk
new file mode 100644 (file)
index 0000000..8e35ac7
--- /dev/null
@@ -0,0 +1,3 @@
+TARGET         := rlm_realm.a
+
+SOURCES                := rlm_realm.c
index 3a4509c..6e5b4d4 100644 (file)
@@ -1,7 +1,7 @@
 TARGET      = @targetname@
 SRCS        = rlm_rediswho.c
 HEADERS     = $(top_builddir)/src/modules/rlm_redis/rlm_redis.h
-RLM_CFLAGS  = -I$(top_builddir)/src/modules/rlm_redis $(INCLTDL) @redis_cflags@
+RLM_CFLAGS  = -I$(top_builddir)/src/modules/rlm_redis @redis_cflags@
 RLM_LIBS    = @redis_ldflags@
 RLM_INSTALL =
 
diff --git a/src/modules/rlm_sim_files/all.mk b/src/modules/rlm_sim_files/all.mk
new file mode 100644 (file)
index 0000000..a357ce8
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET = rlm_sim_files.a
+SOURCES        = rlm_sim_files.c
index 5ab0ab1..c716f02 100644 (file)
@@ -6,7 +6,7 @@ TARGET          = @targetname@
 SRCS           = rlm_sql.c sql.c
 HEADERS                = rlm_sql.h conf.h
 RLM_INSTALL    = install-drivers
-RLM_CFLAGS     = $(INCLTDL) -I$(top_builddir)/src/modules/rlm_sql
+RLM_CFLAGS     = -I$(top_builddir)/src/modules/rlm_sql
 RLM_LIBS       = $(LIBLTDL)
 RLM_SUBDIRS    = drivers
 
diff --git a/src/modules/rlm_sql/all.mk b/src/modules/rlm_sql/all.mk
new file mode 100644 (file)
index 0000000..779aeea
--- /dev/null
@@ -0,0 +1,3 @@
+TARGET         = rlm_sql.a
+SOURCES                = rlm_sql.c sql.c
+# this uses the RLM_CFLAGS and RLM_LIBS and SOURCES defs to make TARGET.
index 7342f10..5d3d1e6 100644 (file)
@@ -2,7 +2,7 @@ include ../../../../../Make.inc
 
 TARGET         = @targetname@
 SRCS           = sql_db2.c
-RLM_SQL_CFLAGS = @sql_ibmdb2_cflags@ $(INCLTDL)
+RLM_SQL_CFLAGS = @sql_ibmdb2_cflags@
 RLM_SQL_LIBS   = @sql_ibmdb2_ldflags@
 
 include ../rules.mak
index 624ab45..aac77af 100644 (file)
@@ -7,7 +7,7 @@ include ../../../../../Make.inc
 TARGET         = @targetname@
 SRCS           = sql_firebird.c sql_fbapi.c
 HEADERS                = sql_fbapi.h
-RLM_SQL_CFLAGS = @sql_firebird_cflags@ $(INCLTDL)
+RLM_SQL_CFLAGS = @sql_firebird_cflags@
 RLM_SQL_LIBS   = @sql_firebird_ldflags@
 
 # this uses the RLM_SQL_CFLAGS and RLM_SQL_LIBS and SRCS defs to make TARGET.
index 8c08088..64af56d 100644 (file)
@@ -2,7 +2,7 @@ include ../../../../../Make.inc
 
 TARGET         = @targetname@
 SRCS           = sql_iodbc.c
-RLM_SQL_CFLAGS = @sql_iodbc_cflags@ $(INCLTDL)
+RLM_SQL_CFLAGS = @sql_iodbc_cflags@
 RLM_SQL_LIBS   = @sql_iodbc_ldflags@
 
 include ../rules.mak
index 9152bf0..a17bb3d 100644 (file)
@@ -2,7 +2,7 @@ include ../../../../../Make.inc
 
 TARGET         = @targetname@
 SRCS           = sql_mysql.c
-RLM_SQL_CFLAGS = @sql_mysql_cflags@ $(INCLTDL)
+RLM_SQL_CFLAGS = @sql_mysql_cflags@
 RLM_SQL_LIBS   = @sql_mysql_ldflags@
 
 include ../rules.mak
index 48d437a..f2430c1 100644 (file)
@@ -80,6 +80,27 @@ static int sql_init_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config)
 
        mysql_init(&(mysql_sock->conn));
        mysql_options(&(mysql_sock->conn), MYSQL_READ_DEFAULT_GROUP, "freeradius");
+
+#if (MYSQL_VERSION_ID >= 50000)
+       if (config->query_timeout) {
+               unsigned int timeout = config->query_timeout;
+
+               /*
+                *      3 retries are hard-coded into the MySQL library.
+                *      We ensure that the REAL timeout is what the user
+                *      set by accounting for that.
+                */
+               if (timeout > 3) timeout /= 3;
+
+               mysql_options(&(mysql_sock->conn), MYSQL_OPT_CONNECT_TIMEOUT,
+                             &timeout);
+               mysql_options(&(mysql_sock->conn), MYSQL_OPT_READ_TIMEOUT,
+                             &timeout);
+               mysql_options(&(mysql_sock->conn), MYSQL_OPT_WRITE_TIMEOUT,
+                             &timeout);
+       }
+#endif
+
 #if (MYSQL_VERSION_ID >= 40100)
        sql_flags = CLIENT_MULTI_RESULTS | CLIENT_FOUND_ROWS;
 #else
index 000e0b3..b9b4bcf 100644 (file)
@@ -2,7 +2,7 @@ include ../../../../../Make.inc
 
 TARGET         = @targetname@
 SRCS           = sql_oracle.c
-RLM_SQL_CFLAGS = @sql_oracle_cflags@ $(INCLTDL)
+RLM_SQL_CFLAGS = @sql_oracle_cflags@
 RLM_SQL_LIBS   = @sql_oracle_ldflags@
 
 include ../rules.mak
index 55076a2..e564426 100644 (file)
@@ -2,7 +2,7 @@ include ../../../../../Make.inc
 
 TARGET         = @targetname@
 SRCS           = sql_postgresql.c
-RLM_SQL_CFLAGS = @postgresql_cflags@ $(INCLTDL)
+RLM_SQL_CFLAGS = @postgresql_cflags@
 RLM_SQL_LIBS   = @postgresql_ldflags@
 
 include ../rules.mak
index b534b63..8151a5b 100644 (file)
@@ -2,7 +2,7 @@ include ../../../../../Make.inc
 
 TARGET         = @targetname@
 SRCS           = sql_sqlite.c
-RLM_SQL_CFLAGS = @sql_sqlite_cflags@ $(INCLTDL)
+RLM_SQL_CFLAGS = @sql_sqlite_cflags@
 RLM_SQL_LIBS   = @sql_sqlite_ldflags@
 
 include ../rules.mak
index 02dc6b9..8dc15d3 100644 (file)
@@ -8,7 +8,7 @@ include ../../../../../Make.inc
 TARGET         =
 #TARGET         = rlm_sql_sybase
 SRCS           = sql_sybase.c
-RLM_SQL_CFLAGS =  $(INCLTDL)  -I/opt/sybase/OCS-12_0/include
+RLM_SQL_CFLAGS =   -I/opt/sybase/OCS-12_0/include
 RLM_SQL_LIBS   =  -L/opt/sybase/OCS-12_0/lib -ltcl -lcomn -lintl -lnsl -ldl -lm -lcs -lct
 
 include ../rules.mak
index 1a28477..55bd9bf 100644 (file)
@@ -2,7 +2,7 @@ include ../../../../../Make.inc
 
 TARGET         = @targetname@
 SRCS           = sql_unixodbc.c
-RLM_SQL_CFLAGS = @sql_unixodbc_cflags@ $(INCLTDL)
+RLM_SQL_CFLAGS = @sql_unixodbc_cflags@
 RLM_SQL_LIBS   = @sql_unixodbc_ldflags@
 
 include ../rules.mak
diff --git a/src/modules/rlm_sql_log/all.mk b/src/modules/rlm_sql_log/all.mk
new file mode 100644 (file)
index 0000000..ec12feb
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET      = rlm_sql_log.a
+SOURCES        = rlm_sql_log.c
index 2e6f72e..7ec5eeb 100644 (file)
@@ -199,14 +199,14 @@ static size_t sql_escape_func(char *out, size_t outlen, const char *in)
 
 static size_t sql_utf8_escape_func(char *out, size_t outlen, const char *in)
 {
-       int len = 0;
-       int utf8 = 0;
+       size_t len = 0;
+       size_t utf8 = 0;
 
        while (in[0]) {
                /* 
                 * Skip over UTF8 characters
                 */
-               utf8 = fr_utf8_char((uint8_t *)in);
+               utf8 = fr_utf8_char((const uint8_t *)in);
                if (utf8) {
                        if (outlen <= utf8) {
                                break;
diff --git a/src/modules/rlm_sqlcounter/all.mk b/src/modules/rlm_sqlcounter/all.mk
new file mode 100644 (file)
index 0000000..b70adb5
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET      = rlm_sqlcounter.a
+SOURCES        = rlm_sqlcounter.c
index 548e69a..2864865 100644 (file)
@@ -1,7 +1,7 @@
 TARGET      = @targetname@
 SRCS        = rlm_sqlhpwippool.c
 HEADERS     =
-RLM_CFLAGS  = $(INCLTDL) @sqlhpwippool_cflags@ -I$(top_builddir)/src/modules/rlm_sql
+RLM_CFLAGS  = @sqlhpwippool_cflags@ -I$(top_builddir)/src/modules/rlm_sql
 RLM_LIBS    = $(LIBLTDL) @sqlhpwippool_ldflags@
 RLM_INSTALL =
 
index 3114c16..af28710 100644 (file)
@@ -7,7 +7,7 @@ INCLUDE += -I/usr/local/include/
 TARGET      = @targetname@
 SRCS        = rlm_sqlippool.c
 HEADERS     = $(top_builddir)/src/modules/rlm_sql/rlm_sql.h
-RLM_CFLAGS  = -I$(top_builddir)/src/modules/rlm_sql $(INCLTDL)
+RLM_CFLAGS  = -I$(top_builddir)/src/modules/rlm_sql
 RLM_LIBS    =
 RLM_INSTALL =
 
diff --git a/src/modules/rlm_sqlippool/all.mk b/src/modules/rlm_sqlippool/all.mk
new file mode 100644 (file)
index 0000000..108112c
--- /dev/null
@@ -0,0 +1,4 @@
+TARGET      = rlm_sqlippool.a
+SOURCES        = rlm_sqlippool.c
+
+SRC_INCDIRS := $(top_builddir)/src/modules/rlm_sql
diff --git a/src/modules/rlm_unix/all.mk b/src/modules/rlm_unix/all.mk
new file mode 100644 (file)
index 0000000..95c0c1d
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET     = rlm_unix.a
+SOURCES       = rlm_unix.c
index bd3784f..5c0fe0f 100644 (file)
@@ -71,16 +71,14 @@ static const CONF_PARSER module_config[] = {
 /*
  *     The Group = handler.
  */
-static int groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request,
+static int groupcmp(void *instance, REQUEST *req, UNUSED VALUE_PAIR *request,
                    VALUE_PAIR *check, VALUE_PAIR *check_pairs,
                    VALUE_PAIR **reply_pairs)
 {
        struct passwd   *pwd;
        struct group    *grp;
        char            **member;
-       char            *username;
        int             retval;
-       VALUE_PAIR      *vp;
 
        instance = instance;
        check_pairs = check_pairs;
diff --git a/src/modules/rlm_wimax/Makefile b/src/modules/rlm_wimax/Makefile
deleted file mode 100644 (file)
index 5ef0791..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-TARGET         = rlm_wimax
-SRCS           = rlm_wimax.c
-HEADERS                = 
-RLM_CFLAGS     =
-RLM_LIBS       = $(OPENSSL_LIBS)
-
-include ../rules.mak
-
-$(STATIC_OBJS): $(HEADERS)
-
-$(DYNAMIC_OBJS): $(HEADERS)
diff --git a/src/modules/rlm_wimax/all.mk b/src/modules/rlm_wimax/all.mk
new file mode 100644 (file)
index 0000000..af16806
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET         = rlm_wimax.a
+SOURCES                = rlm_wimax.c
index a9067f3..cd159a1 100644 (file)
@@ -116,14 +116,13 @@ endif
 WHERE=$(shell pwd)
 
 build-module: $(TARGET).la $(RLM_UTILS)
-       @[ "x$(RLM_SUBDIRS)" = "x" ] || $(MAKE) $(MFLAGS) WHAT_TO_MAKE=all common
        @[ -d $(top_builddir)/src/modules/lib/.libs ] || mkdir $(top_builddir)/src/modules/lib/.libs
        @for x in .libs/* $^; do \
                rm -rf $(top_builddir)/src/modules/lib/$$x; \
                ln -s $(WHERE)/$$x $(top_builddir)/src/modules/lib/$$x; \
        done
 
-$(TARGET).la: $(LT_OBJS)
+$(TARGET).la: $(RLM_SUBDIRS) $(LT_OBJS)
        @echo LINK $@ $^
        @$(LIBTOOL) --quiet --mode=link $(CC) -release $(RADIUSD_VERSION) \
            -module $(LINK_MODE) $(LDFLAGS) $(RLM_LDFLAGS) -o $@     \